.net 一般NOT约束,其中T:!I无数

jjhzyzn0  于 2023-01-14  发布在  .NET
关注(0)|答案(7)|浏览(145)

正如标题所示,在c#4中声明类型求反约束是可能的吗?

t8e9dugd

t8e9dugd1#

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

xu3bshqb

xu3bshqb2#

我发现我自己在尝试实现评论中提到的同样的案例

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

swvgeqrz3#

据我所知,那是不可能的。
您可以做的是一些运行时检查:

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

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

    // ...

    return true;
}
gstyhher

gstyhher4#

其一个用途是选项类型。

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
    }
}

运行时检查当然可以工作,但是您不会在编译时获得类型检查的好处。

l7wslrjt

l7wslrjt5#

不,但可以用“是”来确认然后适当处理...

pxy2qtax

pxy2qtax6#

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

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)
    {

    }
jv4diomz

jv4diomz7#

使用约束是为了确保所使用的类型具有一些您想要使用的属性/方法/... *。
带有类型否定约束的泛型没有任何意义,因为没有必要知道 * 您不想使用的 * 某些属性/方法是否缺失。

相关问题