C#中使用泛型的函数声明

时间:2011-11-15 20:29:13

标签: c# generics

我有一个声明如下的函数:

public static string MultiWhereToString(List<WhereCondition<T>> whereConditions)

我正在尝试传递一个名为whereAnd的变量,其变量如下:

private List<WhereAndCondition<T>> whereAnd = new List<WhereAndCondition<T>>();

WhereAndConditionWhereCondition的子类。声明如下:

public class WhereAndCondition<T> : WhereCondition<T>, IConditional where T : DatabaseObject

我的问题是,如果我尝试执行以下代码:

private List<WhereAndCondition<T>> whereAnd = new List<WhereAndCondition<T>>();
MultiWhereToString(whereAnd);

我收到以下错误:

Error 3 Argument 1: cannot convert from 'System.Collections.Generic.List<BrainStorm.WhereAndCondition<T>>' to 'System.Collections.Generic.List<BrainStorm.WhereCondition<T>>'

为什么有任何想法?我认为它与WhereCondition类的泛型有关。

6 个答案:

答案 0 :(得分:2)

假设:

class A {}
class A : B {}

List<B>的对象 List<A>的实例。因此,您无法将List<WhereAndCondition>投射到List<WhereCondition>。你可以使用:

MultiWhereToString(whereAnd.OfType<WhereCondition>().ToList());

(可能还有一个涉及inout方差注释的解决方案,但我对它们并不十分熟悉。)

答案 1 :(得分:2)

您的函数被定义为采用WhereCondition列表,但您将其传递给WhereAndCondition列表:

MultiWhereToString(List<WhereCondition<T>> whereConditions)

private List<WhereAndCondition<T>> whereAnd = new List<WhereAndCondition<T>>(); 
MultiWhereToString(whereAnd); 

在.NET 4中支持列表差异有限。请参阅this question

答案 2 :(得分:2)

必须在编译时明确知道泛型,因为它们是生成的。

为什么不使用:

private List<WhereCondition<T>> whereAnd = new List<WhereCondition<T>>();

因此,您仍然可以将WhereAndCondition个对象添加到whereAnd

答案 3 :(得分:2)

您可以将WhereCondition<T>方法中的整个MultiWhereToString替换为仅限WhereCondition<T>的其他通用类型。

替换:

public static string MultiWhereToString(List<WhereCondition<T>> whereConditions)

使用:

public static string MultiWhereToString<TType>(List<TType> whereConditions) where TType: WhereCondition<T>

或者改变:

private List<WhereAndCondition<T>> whereAnd = new List<WhereAndCondition<T>>();

为:

private List<WhereCondition<T>> whereAnd = new List<WhereCondition<T>>();

让继承为你照顾剩下的事。

答案 4 :(得分:2)

这似乎是一个协方差/逆转问题。

简化为:

    public class WhereCondition
    {
    }

    public class WhereAndCondition : WhereCondition
    {
    }

    public class blah
    {
        public static void Blah()
        {
            List<WhereAndCondition> whereAnd = new List<WhereAndCondition>();
            MultiWhereToString(whereAnd);
        }

        public static string MultiWhereToString(List<WhereCondition> whereConditions)
        {
            return null;
        }
    }

它不会起作用,因为WhereAndConditions列表无法强制转换为WhereConditions列表:

想象一下这样。你有一个长颈鹿的名单,这个方法是要求一份动物名单。

不知道他们将如何处理列表动物(比如尝试添加马),这些类型是不兼容的,但是如果你把它改成这样的话:

        public static string MultiWhereToString(IEnumerable<WhereCondition> whereConditions)
        {
            return null;
        }

然后方差可以启动,并为您提供您正在寻找的东西。

答案 5 :(得分:2)

我建议使用接口:

public static string MultiWhereToString(IEnumerable<ICondition<T>> whereConditions)

这会让你在调用这个方法时有更多的自由。