【问题标题】:generic NOT constraint where T : !IEnumerable通用 NOT 约束,其中 T : !IEnumerable
【发布时间】:2012-02-02 09:26:15
【问题描述】:

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

【问题讨论】:

  • 即使有,你能描述一个用例吗?
  • 看到你有这样的要求很奇怪。您只能针对您知道属于一类家族的类型 T 进行编码。否则你怎么能用泛型编码?在这种情况下您不需要泛型,或者您需要修改您的用例。
  • 感兴趣的用例是允许以下重载共存 void doIt<T>(T what){} void doIt<T>(IEnumerable<T> whats){} - 目前存在歧义,因为第一种方法中的 T 可能是 @987654324 @(所以我想指定 T 不应该是 IEnumerable)...
  • 我提请您注意这样一个事实,即具有采用 T 和 T 序列的方法的类型通常对这两种方法具有不同的名称。例如,在 List 中的 Add 和 AddRange。这是有原因的。遵循这种模式。
  • 为什么是近距离投票?这个问题的答案可能是“否”,但这并不意味着这个问题没有价值。

标签: c# .net generics ienumerable


【解决方案1】:

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

【讨论】:

  • 这个概念将来会应用到 C# 和/或 CLR 中吗?
  • @RandRandom:我还没有听说过任何计划。
  • 请添加与该答案对应的最新 C# 版本...以防将来必须更改...
  • @Serge:我宁愿不这样做。它适用于网站上几乎所有基于语言的问题的答案,并且每次有新版本的 C# 时都重新访问每个答案是不可行的。
  • @TravisReed:老实说,我认为这会给很多答案增加很多噪音。请注意,问题已经指定了 C# 的版本,人们应该查看上下文 IMO 的答案日期。
【解决方案2】:

我发现自己在尝试实现 cmets 中提到的相同案例

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】:

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

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

    public bool MyGenericMethod<T>()
    {
        // if (T is IEnumerable) // don't do this
    
        if (typeof(T).GetInterface("IEnumerable") == null)
            return false;
    
        // ...
    
        return true;
    }
    

    【讨论】:

    • 你不能像那样使用is - 它测试一个object是否与一个类型兼容。
    • 你的意思是if (typeof(T) == typeof(IEnumerable)) {}
    【解决方案4】:

    一种用途是选项类型。

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

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

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

        据我所知,Not 约束是不可能的。您可以使用基类和/或接口来约束泛型。面对导致运行时失败的类似问题,我在 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)
            {
        
            }
        

        【讨论】:

          【解决方案7】:

          你使用了一个约束,所以你可以确保你使用的类型有一些属性/方法/...你想使用

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

          【讨论】:

          • 显然你没有收到错误:##'' 不能同时实现 '>' 和 '>' 因为它们可能统一一些类型参数替换## .. 当你想指定 genericstype2 不能是 generictype4 时,肯定会有这种情况
          • 我能够通过使用一系列抽象类来解决我的场景,这些抽象类实现了类似接口的实例,并继承了抽象类。我想这就是 Action 依此类推..
          猜你喜欢
          • 1970-01-01
          • 2011-02-27
          • 2013-07-22
          • 2021-01-17
          • 1970-01-01
          • 2017-01-21
          • 1970-01-01
          • 2015-06-25
          • 1970-01-01
          相关资源
          最近更新 更多