Val*_*mas 8 c# ref generic-list derived-class
我如何传递一个列表,该列表是一个DerivedObjects列表,其中Method期望一个BaseObjects列表.我正在转换列表.ToList<BaseClass>(),我想知道是否有更好的方法.我的第二个问题是语法不正确.我试图传递列表byref,我收到一个错误:'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);
}
}
Run Code Online (Sandbox Code Playgroud)
解决了:
类似的方法解决了我的问题.
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);
}
Run Code Online (Sandbox Code Playgroud)
感谢所有帮助解决这个问题以及其他SO问题的人.
Jon*_*eet 14
该ref部分很容易:通过引用传递参数,它必须是一个变量,基本上.所以你可以写:
List<BaseClass> tmp = myDerivedList.ToList<BaseClass>();
PassList(ref tmp);
Run Code Online (Sandbox Code Playgroud)
......但这不会影响价值myDerivedList或内容本身.
在ref这里是没有意义的,无论如何,因为你永远不会改变的值myList的方法中反正.了解更改参数值和更改参数值引用的对象内容之间的区别非常重要.有关详细信息,请参阅有关参数传递的文章.
现在,为什么你不能通过你的列表 - 这是为了保持类型安全.假设你可以这样做,我们可以写:
List<OtherDerivedClass> list = new List<OtherDerivedClass>();
PassList(list);
Run Code Online (Sandbox Code Playgroud)
现在,将尝试添加的一个实例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 );
Run Code Online (Sandbox Code Playgroud)
C#4允许在某些情况下的通用差异 - 但在这种特定情况下它没有帮助,因为你正在做一些从根本上说不安全的事情.通用方差是一个相当复杂的话题,但-因为你还在学习如何参数传递的作品,我会强烈建议你不要管它的时刻,直到你的语言的其余部分更加自信.
如果您必须保留ref,您可以这样做:
var list = myDerivedList.ToList<BaseClass>();
PassList(ref list);
// SYNTAX ERROR ABOVE IS - 'ref' argument is not classified as a variable
Run Code Online (Sandbox Code Playgroud)
对于ref参数来说,它需要一个变量来引用。当动态创建时,稍后在代码中没有任何内容可以引用,因此它确实没有任何意义。