【问题标题】:Why is Nullable<T> considered a struct and not a class?为什么 Nullable<T> 被认为是结构而不是类?
【发布时间】:2013-12-14 21:57:55
【问题描述】:

我正在尝试定义一个泛型类,它采用可以设置为 null 的任何类型:

public abstract class BundledValue_Classes<T> 
    where T : class
{
    private Tuple<T, object> _bundle= new Tuple<T, object>();
    public T Value
    { 
        get { return _bundle == null ? null : _bundle.Item1; }
        set { _bundle = new Tuple<T, object>(value, obj); }
    }
    //...

这很好用。我还想创建一个可以采用任何原始类型(int、double 等)的派生类,并简单地将其解析为与上述类相同的类,但原始类包含在 Nullable 中

public abstract class BundledValue_Structs<T> 
    : BundledValue_Classes<T?> 
    where T : struct
{
   //...
}

但由于某种原因,这不起作用。我得到错误:The type 'T?' must be a reference type in order to use it as parameter 'T' in the generic type or method 'BundledValue_Classes&lt;T&gt;'

我想在这里做什么很清楚吗?我不想复制粘贴整个BundledValue_Classes&lt;T&gt; 类的内容来处理包裹在Nullable&lt;T&gt; 中的原语的情况。

也许有一些方法可以在BundledValue_Classes&lt;T&gt; 上设置类型约束,这样它不仅可以接受类,还可以接受任何可以分配空值的类型(包括Nullable&lt;T&gt; 类型,这似乎是唯一的例外)规则。)

【问题讨论】:

  • 旁注:我强烈建议您遵循 .NET 命名约定。 customTuple&lt;T&gt; 这个名字不这样做...
  • @JonSkeet 这只是我从课堂上删除了很多杂物以使示例更清晰。
  • 提供简洁、简短的示例很好 - 但忽略正常的命名约定并没有增加清晰度。
  • 为什么会有Java标签?删除它..

标签: c# generics nullable type-constraints


【解决方案1】:

Nullable&lt;T&gt; 一个结构,as per the documentation。它根本不是一个类。是一个值类型,从字段上看有点像这样:

public struct Nullable<T>
{
    private readonly T value;
    private readonly bool hasValue;
}

Nullable&lt;T&gt; 类型的null 值不是空引用,它只是hasValue 字段为假的值。

请注意,Nullable&lt;T&gt; 不满足 where TFoo : struct 约束的条件,因为这实际上是 不可为空 值类型约束。基本上Nullable&lt;T&gt; 不满足classstruct 约束。 确实 没有限制只允许可空类型(参考或Nullable&lt;T&gt;)。

【讨论】:

  • 那么Nullable&lt;T&gt; 是否具有特殊语法之外的魔力?这是一个既不是: class也不是: struct的类型?
  • @delnan:这是一个既不满足这些类型约束的类型,是的。它还具有特殊的拳击行为。
  • 感谢@JonSkeet - 发布了一个后续问题,询问是否有解决方法来复制课程:stackoverflow.com/questions/20597586/…
  • 不需要变通方法。请参阅我对您的后续问题的回复。 Nullable 是一个结构,但可以为空的类型,即 int?double?,是满足 说明符的类型。
  • @drankin2112:OP 希望将类型参数限制为可空类型。你根本做不到。说“只是不要使用Bundled&lt;float&gt;”不是一个好的答案,IMO。
【解决方案2】:

如前所述,Nullable&lt;T&gt; 类型是一个结构,它封装了T 和一个指示其是否有效的标志。因为 .NET 的实现者没有看到能够拥有一个可以封装任何事物并指示它是否有效的类型有任何用处,他们决定他们不想允许 Nullable&lt;Nullable&lt;T&gt;&gt; [一个决定顺便说一句,我不喜欢],而不是仅仅为Nullable&lt;T&gt; 中的泛型参数提出一个特殊的约束,他们决定即使Nullable&lt;T&gt; 是一个结构,它也不应该满足struct 类型约束.

就我个人而言,我宁愿看到Nullable&lt;T&gt; 只是一个“普通”结构,具有bool 类型的暴露字段和不受约束的T,例如可以使用它。 Dictionary.TryGetValue 返回一个值并指出它是否有效(不管TValue 是一个类、一个不可为空的结构还是一个Nullable&lt;T&gt;),或者让它是一个包含T 的类。与someNullable.HasValue 相比,能够说someNullable != null 作为捷径的价值与它引起的混乱和复杂性相比是微不足道的。尽管如此,.NET 就是这样。就个人而言,我建议通常避免可空类型,因为如果不先复制值,就无法对可空类型做很多事情。这些类型在线程安全方面也有一些奇怪的怪癖(例如,接收Nullable&lt;T&gt; 并观察到HasValue 的代码不能安全地假设GetValueOrDefault 将返回Default(T),即使没有任何东西可以修改@987654340 @,因为它已收到)。

【讨论】:

    猜你喜欢
    • 2017-04-01
    • 2021-03-26
    • 2015-08-12
    • 2019-06-16
    • 2014-08-05
    • 1970-01-01
    • 1970-01-01
    • 2011-05-12
    相关资源
    最近更新 更多