【问题标题】:Do you gain any operations when you constrain a generic type using where T : struct?当您使用 where T : struct 约束泛型类型时,您是否获得任何操作?
【发布时间】:2010-03-24 23:02:13
【问题描述】:

这可能是一个有点抽象的问题,所以提前道歉。

我正在研究 .NET 中的泛型,并且想知道 where T : struct 约束。

我了解这允许您将类型限制为值类型。我的问题是,在没有任何类型限制的情况下,您可以对 T 进行有限数量的操作。

当您指定where T : struct 时,您是否获得了使用任何其他操作的能力,或者是限制您可以传入的类型的唯一值?

编辑

到目前为止,一些有趣的答案,谢谢。 我想我实际上要问的问题是,如果我要写,(在关于如何使用泛型的讨论中),

“现在你已经约束了 值类型的类型参数,您可以 也可以在/与那种类型的对象上做___________________”

有什么要填的吗?我可以考虑其他约束条件,但不是这个。

【问题讨论】:

    标签: c# .net vb.net generics


    【解决方案1】:

    T : struct 为您带来的只是一个隐含的new() 构造函数,以及一些涉及null 的明显内容。或许更重要的是,调用者不能使用类、接口或Nullable<T>

    您追求什么类型的操作?对于运营商,请尝试 4.0 中的 dynamic,或 3.5 中的 MiscUtil

    【讨论】:

      【解决方案2】:

      相对于其他可能的约束集,您获得的唯一好处是能够使用 Nullable<T> 类型的值(这就是为什么 T: struct 禁止调用者将 Nullable<T> 作为类型参数传递 - 它可以'不能嵌套)。

      【讨论】:

      • 这只是“使用约束 T : struct,您可以将 T 作为任何其他需要 T : struct 的泛型类型的实际参数”的特例。
      【解决方案3】:

      不,通过指定 where T: struct 泛型类型约束,您不会对 T 进行任何操作。您将调用者限制为仅指定值类型(Nullable<T> 值类型除外,这是不允许的)。

      【讨论】:

      • new T() 操作除外。你失去比较Tnull的能力。
      • 输不赢,new T() 真的算不上赢,因为default(T) 的结果是一样的。
      • 对,对(在new T()===default(T))。我可以争辩说,让编译器发现一个明显的脑死亡测试正在获得,但我不得不同意你的观点;-p
      • @HåvardS:如果T 是受接口约束的结构类型,那么default(T) 将是相关接口的有效实现。相比之下,如果它是受接口约束的类类型,default(T) 将为 null,这不是任何接口的有效实现。
      • @supercat 是的,这正是我和@Marc Gravell 所说的(忽略T 不限于struct 的情况,因为问题没有考虑到这种情况)。
      【解决方案4】:

      一种保证在可变类中不可用并且可能有时在可变结构中可用的操作类型是使用赋值运算符复制事物状态的能力。将变异接口与结构一起使用很棘手,因为尝试在只读上下文中的结构上使用变异接口将产生可以干净编译但不起作用的代码(我真的希望编译器能够识别结构和接口成员上的属性表示它们不应在只读结构上使用)。尽管如此,在某些情况下这样的东西还是有用的。

      例如,如果算法需要能够存储枚举器的状态并将枚举器恢复到其保存的状态,并且如果枚举器是泛型类型 TEnum 被限制为 structIEnumerator<T>, it may be possible to copy theTEnum to a local variable of that type and then later copy it back. Note that this would work with some but not allstructtypes which implementIEnumerable; such a technique should in practice probably only be used with interfaces that explicitly document a requirement that all legitimate struct-type implementations must exhibit value semantics (IEnumerator`没有这样的书面要求)。

      请注意,代码可能会使用按值复制结构的能力(当它存在时),这确实排除了使用接口的类类型实现的稍微不同(可能效率较低)的方法的可能性。函数签名:

      void ActOnSequence<T>(T theEnumerator) where T:struct, IEnumerator<String>;
      void ActOnSequence(IEnumerator<String> theEnumerator);
      

      可以共存并毫无困难地使用。前者将在接口的值类型实现上调用,而后者将在堆类型实现上调用。请注意,如果没有struct 约束,就不可能同时拥有上述两种方法并自动调用正确的方法。

      【讨论】:

        猜你喜欢
        • 2017-01-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-29
        • 2020-06-28
        相关资源
        最近更新 更多