【问题标题】:What if T is void in Generics? How to omit angle brackets如果泛型中的 T 为空怎么办?如何省略尖括号
【发布时间】:2012-10-26 08:19:32
【问题描述】:

我有一个此类:

class A<TResult>
{
     public TResult foo();
}

但有时我需要把这个类当作一个非泛型类来使用,即TResult的类型是void
我无法通过以下方式实例化该类:

var a = new A<void>();

另外,我宁愿不指定省略尖括号的类型:

var a = new A();

我不想重写整个类,因为它做同样的事情。

【问题讨论】:

  • @Davio 是的,但这太可怕了......
  • 在这种情况下,您必须在没有约束的情况下创建一个单独的类A。但是没有 T 的类实现会是什么样子呢?你有一个T foo() 方法。如果无效,T 应该是什么?
  • 如果你有需要,那就做一个非泛型等效类。
  • 你可以通过class A:A&lt;object&gt;{}隐藏恐怖
  • 是的,它有效。我也在等待 Rafal 的回答,这样我就可以投票了。

标签: c# generics void


【解决方案1】:

void 在 C# 中不是真正的类型,即使在 FCL 中有对应的 System.Void 结构。恐怕您需要像这样的非通用版本:

class A
{
   //non generic implementation
}

class A<T> : A
{
   //generic implementation 
}

您可以在 FCL 中看到 System.Action/System.Action&lt;T&gt;,而不是 System.Action&lt;void&gt;,以及 Task,而不是 Task&lt;void&gt;

编辑来自CLI specification(ECMA-335)

以下类型不能用作参数 实例化(泛型类型或方法):

Byref 类型(例如,System.Generic.Collection.List`1 是 无效)

包含可以指向 CIL 评估堆栈的字段的值类型(例如,List

void(例如,List 无效)

【讨论】:

    【解决方案2】:

    正如我在评论中发布的,您可以通过从泛型类继承使其看起来不错:

    class A:A<object>
    {
    }
    

    这清楚地隐藏了泛型参数,但请注意,根据我的经验,这是继承类的错误方式,每次这样做我都会后悔,因为我的类变得更加复杂。

    【讨论】:

    • 我可以重用一个有数百行代码的类,用这个技巧只添加几十行+1
    【解决方案3】:

    void 根本不是 C# 中的类型,因此您不能将其作为类型参数。但是,尽管如此,有时您还是想要一个功能,就好像它是一个功能一样。

    在这种情况下,你可以使用一个简单的替换类型,很可能是一个非常小的结构,例如在 Reactive Extensions 中使用的System.Reactive.Unit

    【讨论】:

      【解决方案4】:

      另一个选择(这似乎是 falanwe 的意思)是使用 NullObject 设计模式。 http://sourcemaking.com/design_patterns/null_object

      【讨论】:

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