当param类型为List <baseclass>时,如何传递List <derivedclass>?</baseclass> </derivedclass>

时间:2011-10-04 04:12:11

标签: c# derived-class generic-list ref

如何传递一个列表,该列表是一个DerivedObjects列表,其中Method需要一个BaseObject列表。我正在转换列表.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);
    }
}

解决:

类似的方法解决了我的问题。

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问题的人。

3 个答案:

答案 0 :(得分:14)

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而非BaseClassBanana / Apple作为两个派生类,PassList添加{ {1}}列出了它:

Apple

C#4在某些情况下允许泛型差异 - 但在这种特殊情况下它不会有帮助,因为你正在做一些从根本上说不安全的事情。通用方差是一个相当复杂的主题 - 因为你仍然在学习参数传递是如何工作的,我会强烈建议你暂时不管它,直到你更多对其他语言充满信心。

答案 1 :(得分:2)

如果您必须保留ref,则可以执行以下操作:

var list = myDerivedList.ToList<BaseClass>();
PassList(ref list);
// SYNTAX ERROR ABOVE IS - 'ref' argument is not classified as a variable

对于ref参数,它需要一个变量来引用。在动态创建时,以后在代码中没有任何内容可供参考,所以它实际上没有任何意义。

答案 2 :(得分:0)

首先,在您提供的代码中,您不需要ref因为您没有以任何方式真正更改目标(引用)myList。 然后当然你得到了ref myDerivedList.ToList<..>()的错误,因为你可以通过一个byref改变指向变量的位置,但是你不给一个变量,你给出一个(所以只是阅读编译器抱怨;))

要指出:请阅读Co- and Contravariance - 如果您使用的是.net 4.0