简体   繁体   English

IList的 <IWhatever> 作为方法参数

[英]IList<IWhatever> as a method parameter

I have two IList<ICat> and I'm trying to create a method which takes an IList<ICat> and does some work. 我有两个IList<ICat> ,我正在尝试创建一个方法,它采用IList<ICat>并做一些工作。 I'm having problems trying to pass either an IList<PussyCat> or IList<OtherCat> to it, both PussyCat and OtherCat implement ICat . 我在尝试将IList<PussyCat>IList<OtherCat>传递给它时PussyCat问题, PussyCatOtherCat实现了ICat

I've tried: 我试过了:

List<PussyCat> cats = ...
DoWork((IList<ICat>)cats);

and just 只是

DoWork(cats);

But neither compile. 但是没有编译。 Any ideas? 有任何想法吗?

C# generics are invariant. C#泛型是不变的。 It means List<string> is not a List<object> . 这意味着List<string>不是List<object>

C# 4.0 introduces safe covariance/contravariance but still, you wouldn't be able to pass List<string> as List<object> . C#4.0引入了安全协方差/逆变,但仍然无法将List<string>作为List<object>传递。 The reason is: 原因是:

List<string> x = new List<string>();
List<object> o = x; // assume this statement is valid
o.Add(5); // Adding an integer to a list of strings. Unsafe. Will throw.

Arrays, on the other hand are covariant. 另一方面,数组是协变的。 You can pass a string[] to a method that expects object[] . 您可以将string[]传递给期望object[]

There are two alternatives: 有两种选择:

  1. Make your method like this: 使你的方法像这样:

     public void DoWork< T > (IList< T > cats_) where T : ICat { //Do work; } 
  2. The other possibility is to have a method like 另一种可能性是有一个方法

     public void DoWork(IList< ICat > cats_) { //Do work; } 

    and call it in the following manner: 并按以下方式调用它:

     { //....Assuming: IList<PussyCat> iListOfPussyCats List<PussyCat> pussyCats = new List<PussyCats>(iListOfPussyCats); DoWork(pussyCats.ConvertAll<ICat>( c => c as ICat); } 

If the method doesn't truly require direct indexing ( IList<T> ) and doesn't require adding/removing items ( ICollection<T> ), then pass an IEnumerable<T> . 如果该方法不真正需要直接索引( IList<T> )并且不需要添加/删除项( ICollection<T> ),则传递IEnumerable<T> The Cast<T>() extension methods allow casting any IList of [insert ICat -derived type] to be passed as an IEnumerable<ICat> . Cast<T>()扩展方法允许将[insert ICat -derived type]的任何IList转换为IEnumerable<ICat>

Till C# 4.0 arrives which has support for co and contra variance you might be able to get away with something like this: 直到C#4.0到达,它支持co和contra变化,你可能会得到这样的东西:

public void DoWork(IEnumerable<ICat> cats)
{
  //do something 
}
 List<PussyCat> pussyCats = new List<PussyCat>;
 List<OtherCat> otherCats = new List<OtherCat>;
 DoWork(pussyCats.OfType<ICat>);
 DoWork(otherCats.OfType<ICat>);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM