C#中任意数量的类型参数

时间:2011-03-17 18:16:28

标签: c# generics

我需要将一个类型列表传递给一个方法,但我想确保(在编译时)所有这些都继承自BaseType。 另外,我不知道必须传递多少种类型。

所以我认为这将是一个糟糕的方式:

public void DoSomething(params Type[] types)

所以我到目前为止所做的事情是这样的:

private void DoSomething(params Type[] types)

public void DoSomething<T1>() 
    where T1 : BaseType
{ 
    DoSomething(typeof(T1)); 
}

public void DoSomething<T1, T2>() 
    where T1 : BaseType
    where T2 : BaseType
{ 
    DoSomething(typeof(T1), typeof(T2)); 
}


public void DoSomething<T1, T2, T3>() 
    where T1 : BaseType
    where T2 : BaseType
    where T3 : BaseType{...}

// and so on...

你明白了。 所以问题是:你能做得更漂亮吗? 因为这不支持任意数量的类型。 在我的场景中,八种或更多种类型并不太常见。

我想将此用作this类型的“魔法”,但调用者没有对容器的引用。

2 个答案:

答案 0 :(得分:6)

没有办法在C#(或CIL)中表示这样的约束,所以你要么必须努力编写所有这些重载,要么放弃编译时的安全性而只是在运行时检查-time。

如果可能,另一种替代方法是编写可以使用示例的重载。这是否有用取决于域名,真的。

public void DoSomething(params BaseClass[] examples)
{
    //null-checks here

   Type[] types = examples.Select(e => e.GetType())
                          .ToArray();
   //...    
}

用法(假设BaseClassMammal):

// Compiles fine.
DoSomething(new Goat(), new Tiger(), new Lion());

// Won't compile.
DoSomething(new Fish(), new Tiger(), new Lion()); 

这是一个在运行时检查的示例:

public void DoSomething(Type[] types)
{
    //null-checks here

    // Or perhaps you want IsSubclassOf...
   if(types.Any(t => !typeof(BaseClass).IsAssignableFrom(t))
        throw new ArgumentException(...);           
}

答案 1 :(得分:1)

不,泛型类型由命名空间,类名和类型参数的数量定义(即,在同一名称空间中,类型参数的数量相同,您不能拥有同名的类,甚至如果对它们的约束不同的话。)

如果单个类可能有一个未定义数量的类型参数,那么框架就可以利用Action&lt;&gt;和Func&lt;&gt;课程,它没有。