通用NOT约束,其中T:!IEnumerable

时间:2012-01-04 13:16:18

标签: c# .net generics ienumerable

根据标题,是否可以在c#4中声明类型否定约束?

7 个答案:

答案 0 :(得分:41)

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

答案 1 :(得分:4)

据我所知,不可能这样做。

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

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

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

    // ...

    return true;
}

答案 2 :(得分:3)

我发现自己试图实施评论中提到的相同案例

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>());
}

答案 3 :(得分:0)

不,但是可以用“是”来检查,然后适当地处理它......

答案 4 :(得分:0)

您使用约束,以便确保您使用的类型具有一些属性/方法/ ... 您想要使用

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

答案 5 :(得分:0)

一个用途就是选项类型。

Uncaught TypeError: d3.hexbin is not a function

运行时检查当然可行,但在编译时你不会有类型检查的好处。

答案 6 :(得分:-1)

据我所知,没有约束是不可能的。您可以使用基类和/或接口来约束泛型。面对导致运行时失败的类似问题,我在Generic要处理的类上实现了一个接口:

public interface IOperations
{

}

public static T GenericOperationsFactory<T>(ILogger loggerInstance, ref ExecutionContext executionContext) 
        where T: IOperations
{
    var operationsContext = Factories.OperationsContextFactory(loggerInstance, ref executionContext);

    var operations = typeof(T).GetConstructor(new[] { typeof(OperationsContext) }).Invoke(new object[] { operationsContext });

    return (T)operations;
}

public abstract class OperationsBase:IOperations
{
    protected OperationsContext Context { get; set; }

    public OperationsBase(OperationsContext context)
    {
        Context = context;
    }
...

public class ListsOperations : OperationsBase
{
    public ListsOperations(OperationsContext context) :
        base(context)
    {

    }

或者:

public static T GenericOperationsFactory<T>(ILogger loggerInstance, ref ExecutionContext executionContext) 
        where T: OperationsBase
{
    var operationsContext = Factories.OperationsContextFactory(loggerInstance, ref executionContext);

    var operations = typeof(T).GetConstructor(new[] { typeof(OperationsContext) }).Invoke(new object[] { operationsContext });

    return (T)operations;
}

public abstract class OperationsBase
{
    protected OperationsContext Context { get; set; }

    public OperationsBase(OperationsContext context)
    {
        Context = context;
    }
...

public class ListsOperations : OperationsBase
{
    public ListsOperations(OperationsContext context) :
        base(context)
    {

    }