如何传递List参数类型为List时
本文关键字:List BaseClass 类型 参数 DerivedClass 何传递 | 更新日期: 2023-09-27 18:10:17
我如何传递一个列表,这是一个DerivedObjects的列表,其中方法期望一个BaseObjects的列表。我正在转换列表.ToList<BaseClass>()
,我想知道是否有更好的方法。我的第二个问题是语法不正确。我试图通过ref传递列表,我得到一个错误:'ref' argument is not classified as a variable
我如何解决这两个问题?谢谢。
public class BaseClass { }
public class DerivedClass : BaseClass { }
class Program
{
static void Main(string[] args)
{
List<DerivedClass> myDerivedList = new List<DerivedClass>();
PassList(ref myDerivedList.ToList<BaseClass>());
// SYNTAX ERROR ABOVE IS - 'ref' argument is not classified as a variable
Console.WriteLine(myDerivedList.Count);
}
public static void PassList(ref List<BaseClass> myList)
{
myList.Add(new DerivedClass());
Console.WriteLine(myList.Count);
}
}
解决:
类似的方法已经解决了我的问题。
public static void PassList<T>(ref List<T> myList) where T : BaseClass
{
if (myList == null) myList = new List<T>();
// sorry, i know i left this out of the above example.
var x = Activator.CreateInstance(typeof(T), new object[] {}) as T;
myList.Add(x);
Console.WriteLine(myList.Count);
}
感谢所有帮助解决这个问题和其他SO问题的人
ref
部分很容易:通过引用传递参数,它基本上必须是一个变量。所以你可以这样写:
List<BaseClass> tmp = myDerivedList.ToList<BaseClass>();
PassList(ref tmp);
…但不会影响myDerivedList
的值或内容本身。
这里的ref
是毫无意义的,因为无论如何你都不会在方法中改变myList
的值。理解改变参数值和改变参数值所引用的对象的内容之间的区别是很重要的。有关详细信息,请参阅我关于参数传递的文章。
至于为什么不能传入列表,这是为了保证类型安全。假设你可以做到这一点,我们可以这样写:
List<OtherDerivedClass> list = new List<OtherDerivedClass>();
PassList(list);
现在,这将是试图将DerivedClass
的实例添加到List<OtherDerivedClass>
中-这就像将苹果添加到一堆香蕉中…它不工作!c#编译器会阻止你执行这种不安全的操作——它不会让你把一堆香蕉当作水果盘。假设我们确实有Fruit
而不是BaseClass
, Banana
/Apple
作为两个派生类,PassList
将Apple
添加到给定的列表中:
// This is fine - you can add an apple to a fruit bowl with no problems
List<Fruit> fruitBowl = new List<Fruit>();
PassList(fruitBowl);
// This wouldn't compile because the compiler doesn't "know" that in PassList
// you're only actually adding an apple.
List<Apple> bagOfApples = new List<Apple>();
PassList(bagOfApples);
// This is the dangerous situation, where you'd be trying to really violate
// type safety, inserting a non-Banana into a bunch of bananas. But the compiler
// can't tell the difference between this and the previous one, based only on
// the fact that you're trying to convert a List<Banana or Apple> to List<Fruit>
List<Banana> bunchOfBananas = new List<Banana>();
PassList(bunchOfBananas );
c# 4在某些情况下允许泛型方差,但在这种特殊情况下没有帮助,因为你正在做一些根本不安全的事情。泛型方差是一个相当复杂的话题——因为你还在学习参数传递是如何工作的,我强烈建议你暂时把它放在一边,直到你对语言的其余部分更有信心。
如果您必须保留ref
,您可以这样做:
var list = myDerivedList.ToList<BaseClass>();
PassList(ref list);
// SYNTAX ERROR ABOVE IS - 'ref' argument is not classified as a variable
对于ref
参数,它需要一个变量引用。当动态创建时,在后面的代码中没有什么可引用的,所以它真的没有意义。
首先,在您提供的代码中,您不需要ref
,因为您没有以任何方式真正更改目标(引用)myList。当然你会得到ref myDerivedList.ToList<..>()
的错误,因为你可以用byref改变变量指向的位置,但你不给一个变量,你给一个值(所以只是阅读编译器的抱怨;))
对于你的观点:阅读Co- and Contravariance -如果你正在使用。net 4.0