【问题标题】:Implementing Nullable Types in Generic Interface在泛型接口中实现可空类型
【发布时间】:2010-11-23 14:43:08
【问题描述】:

所以在上一个问题中,我询问了有关使用公共类和宾果游戏实现通用接口的问题,它可以工作。但是,我希望传入的类型之一是内置的可为空类型之一,例如:int、Guid、String 等。

这是我的界面:

public interface IOurTemplate<T, U>
    where T : class
    where U : class
{
    IEnumerable<T> List();
    T Get(U id);
}

所以当我这样实现时:

public class TestInterface : IOurTemplate<MyCustomClass, Int32>
{
    public IEnumerable<MyCustomClass> List()
    {
        throw new NotImplementedException();
    }

    public MyCustomClass Get(Int32 testID)
    {
        throw new NotImplementedException();
    }
}

我收到错误消息:类型“int”必须是引用类型才能将其用作泛型类型或方法“TestApp.IOurTemplate”中的参数“U”

我试图推断类型 Int32?,但同样的错误。有什么想法吗?

【问题讨论】:

    标签: c# exception interface reference reference-type


    【解决方案1】:

    我不会真的这样做,但这可能是让它工作的唯一方法。

    public class MyWrapperClass<T> where T : struct 
    {
        public Nullable<T> Item { get; set; }   
    }
    
    public class MyClass<T> where T : class 
    {
    
    }
    

    【讨论】:

      【解决方案2】:

      可空类型不满足classstruct 约束:

      C# 语言规范 v3.0(第 §10.1.5 节:类型参数约束):

      引用类型约束指定用于类型参数的类型实参必须是引用类型。所有已知为引用类型(定义如下)的类类型、接口类型、委托类型、数组类型和类型参数都满足此约束。 值类型约束指定用于类型参数的类型参数必须是不可为空的值类型。

      具有值类型约束的所有不可为空的结构类型、枚举类型和类型参数都满足此约束。 请注意,虽然归类为值类型,但可为空的类型(第 4.1.10 节)不满足值类型约束。具有值类型约束的类型参数不能同时具有构造函数约束。

      【讨论】:

      • 那你有什么建议?
      • 如果您不需要约束,请将其删除。如果您只想使用可为空的类型,请添加值类型约束 (where T:struct) 并在类定义中使用 T?
      • 制定这样的规则有什么意义?当然 Nullable 应该满足结构约束,因为它是一个结构。
      • @buffjape 嗯,它是一个特殊的结构,不满足约束。 Nullable&lt;T&gt; 由运行时特殊处理:当非空 Nullable&lt;T&gt; 值被装箱时,它被装箱为 T 结构,而不是 Nullable&lt;T&gt;。当 null 可空值被装箱时,它只返回一个空引用。基本原理是:想象int? a = null; if (a == null) {...} object o = a; if (o == null) {...},您可能希望两个if 主体一致地执行。事实上,在引入可空类型的 .NET 2.0 早期测试版中,Nullable&lt;T&gt; 只是一个常规结构,? 只是一个语法......
      • ...用于操作 Nullable&lt;T&gt; 值的糖。由于这种差异,Microsoft 决定更改 CLR 以特别对待 Nullable&lt;T&gt;。您无法编写自己的 MyNullable&lt;T&gt; 结构并获得相同的运行时语义。
      【解决方案3】:

      有什么理由需要将类型 U 限制为类?

      public interface IOurTemplate<T, U>
          where T : class
      {
          IEnumerable<T> List();
          T Get(U id);
      }
      
      public class TestInterface : IOurTemplate<MyCustomClass, Int32?>
      {
          public IEnumerable<MyCustomClass> List()
          {
              throw new NotImplementedException();
          }
      
          public MyCustomClass Get(Int32? testID)
          {
              throw new NotImplementedException();
          }
      }
      

      仅供参考:int?Nullable&lt;int&gt; 的 C# 简写。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-12
        • 2020-05-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多