2012-01-04 39 views
36

根据标题,是否可以在c#4中声明类型 - 否定约束?generic NOT constraint where T:!IEnumerable

+6

即使有,你可以描述一个用例? – 2012-01-04 13:18:06

+1

观察你有这样的要求是很奇怪的。您只能针对您认为属于班级家庭的类型T进行编码。你怎么能用泛型编码呢?要么在这种情况下不需要泛型,要么需要修改用例。 – 2012-01-04 13:46:43

+2

感兴趣的用例是允许以下重载并存:void void doIt (T what){} void doIt (IEnumerable whats){} - 目前存在歧义,因为'T '在第一个方法可能是'IEnumerable <>'(所以我想指定'T'不应该是'IEnumerable')... – Cel 2012-01-04 14:14:22

回答

36

不 - 在C#或CLR中都没有这样的概念。

+0

这个概念将来会用于C#和/或CLR吗? – 2015-07-16 14:25:05

+0

@RandRandom:我还没有听说过任何计划。 – 2015-07-16 14:25:47

0

没有,但它是可以检查与“是”,然后处理它适当地...

1

您使用的约束,这样可以保证你使用的类型有一定的属性/方法/ .. 你想用

带类型否定约束的泛型没有任何意义,因为没有任何目的可以知道不想使用某些属性/方法

+0

显然你还没有收到错误:##''不能实现'>'和'>',因为它们可能统一了一些类型参数替换##。 。当然有些情况下,当你想指定genericstype2不能是generictype4 – 2014-10-03 21:26:42

+0

我可以通过使用一系列实现类似接口实例的抽象类来解决我的场景,并继承抽象类..我想那就是Action 等等。 – 2014-10-03 21:39:56

4

据我所知,这是不可能的。

你可以做的是一些运行时检查:

public bool MyGenericMethod<T>() 
{ 
    // if (T is IEnumerable) // don't do this 

    if (typeof(T).GetInterface("IEnumerable") == null) 
     return false; 

    // ... 

    return true; 
} 
+1

你不能像'那样使用' - 它测试一个* object *是否与一个类型兼容。 – 2012-01-04 13:32:27

+2

你的意思是if(typeof(T)== typeof(IEnumerable)){}' – kev 2012-01-04 13:53:43

0

一个使用了这将是一个选项类型。

public class Option<A,B> 
where A : !B 
where B : !A 
{ 
    private readonly A a; 
    private readonly B b; 

    private Option(){} 

    public Option(A a) 
    { 
     this.a = a 
    } 

    public Option(B b) 
    { 
     this.b = b 
    } 
} 

运行时检查当然会起作用,但是在编译时你没有类型检查的好处。

2

我发现我自己想实现在评论中提到的相同的情况下

void doIt<T>(IEnumerable<T> what) { } 
void doIt<T>(T whats) { } 

除外下面的代码来引用第一种方法

doIt(new List<T>()); 

但它实际上引用第二个

一种解决方案是的说法是这样的:

doIt(new List<T>().AsEnumerable<T>()); 

演员可以通过另一个重载隐藏:

void doIt<T>(List<T> whats) { 
    doIt(whats.AsEnumerable<T>()); 
} 
相关问题