我如何传递一个列表,该列表是一个DerivedObjects列表,其中Method期望一个BaSEObjects列表.我正在转换列表.ToList< BaseClass>(),我想知道是否有更好的方法.我的第二个问题是语法不正确.我试图传递列表byref,我得到一个错误:’ref’参数不被归类为变量
我该如何解决这两个问题呢?谢谢.
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的值.了解更改参数值和更改参数值引用的对象内容之间的区别非常重要.有关详细信息,请参见my article on parameter passing.
现在,为什么你不能通过你的列表 – 这是为了保持类型安全.假设你可以这样做,我们可以写:
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允许在某些情况下的通用差异 – 但在这种特定情况下它没有帮助,因为你正在做一些从根本上说不安全的事情.通用方差是一个相当复杂的主题 – 因为你仍然在学习参数传递是如何工作的,我强烈建议你暂时不管它,直到你对其他语言更加自信.