通用NOT约束,其中T: !IEnumerable
本文关键字:IEnumerable 其中 NOT 约束 通用 | 更新日期: 2023-09-27 18:19:20
根据标题,是否可以在c# 4中声明类型否定约束?
感兴趣的用例是允许以下重载共存
void doIt<T>(T what){}
void doIt<T>(IEnumerable<T> whats){}
目前存在歧义,因为第一个方法中的T
可能是IEnumerable<>
(因此我想指定T
不应该是IEnumerable
)
不——c#和CLR中都没有这样的概念。
我发现我自己试图实现相同的情况在评论中提到:
void doIt<T>(IEnumerable<T> what) { }
void doIt<T>(T whats) { }
I 期望引用第一个方法:
doIt(new List<T>());
但是实际上引用了第二个
一种解决方案是将强制转换为实参:
doIt(new List<T>().AsEnumerable<T>());
强制转换可以被另一个重载隐藏:
void doIt<T>(List<T> whats) {
doIt(whats.AsEnumerable<T>());
}
据我所知这是不可能的。
你可以做的是一些运行时检查:
public bool MyGenericMethod<T>()
{
// if (T is IEnumerable) // don't do this
if (typeof(T).GetInterface("IEnumerable") == null)
return false;
// ...
return true;
}
这是一个选项类型。
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
}
}
运行时检查当然可以工作,但是在编译时就没有类型检查的好处了。
不,但是可以用"is"来检查,然后适当地处理它…
据我所知,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)
{
}
你使用一个约束,这样你可以确保你使用的类型有一些属性/方法/…你想用
具有类型否定约束的泛型没有任何意义,因为没有必要知道缺少一些属性/方法您不想使用。