【问题标题】:Avoid using class name for generic static classes with unqualified generic types避免对具有非限定泛型类型的泛型静态类使用类名
【发布时间】:2018-01-04 19:40:36
【问题描述】:

假设我有一个静态类,它定义了一堆如下所示的委托:

namespace MyNamespace {

    public static class Delegates<T> {

        public delegate T Create(T input);
        public delegate T Update(T input);
        public delegate T Get(Guid id);
        public delegate bool Delete(Guid id);

    }

}

然后我有一个使用这些委托的泛型类,其中依赖类的泛型类型与静态类的泛型类型相同。

namespace MyNamespace {

    public class MyClass<T> {

        public void MyMethod(Delegates<T>.Create create) {
            T foo = GenerateSomeT();
            create(foo);
        }

    }

}

我很想在MyMethod 实现中去掉Delegates&lt;T&gt;. 前缀,因为我相信它可以提高代码的可读性。通常我已经从 C# 6 中通过 the "using static" directive 删除了静态类作为前缀。但在这种情况下,T 不是“完全限定类型名称”,所以我看不到实现这一点的方法.我很想做类似以下示例的操作,但这并不像人们期望的那样工作。原因是TMyClass 的范围之外仍未定义。

using static MyNamespace.Delegates<T>;

namespace MyNamespace {

    public class MyClass<T> {

        public void MyMethod(Create create) {
            T foo = GenerateSomeT();
            create(foo);
        }

    }

}

编译器也不允许我在类中移动“使用静态”指令。

是否可以使用using static 指令或其他一些技巧来避免每次消费者想要使用其属性或方法之一时显式声明具有非限定泛型类型的泛型静态类?

【问题讨论】:

  • 您要做的最好的事情是使Delegates&lt;T&gt; 非静态并从它继承。但这在单继承语言中似乎是个坏主意。我不建议反思。就我个人而言,我会接受它并忍受额外的打字和混乱。
  • Delegates 类必须是通用的吗?

标签: c# generics static using using-directives


【解决方案1】:

您不能简单地将Delegates 设为非泛型,而将代表本身设为泛型吗?

public static class Delegates
{
     public delegate T Create<T> Create(T input);
     //etc
}

现在MyClass&lt;T&gt; 中的T 应该在范围内:

using static Delegates;

public class MyClass<T>
{

    public void MyMethod(Create<T> create)
    {
         //...
    }
}

但是一旦你到了这一点,你就必须意识到这是没有意义的。委托本身就是类型,它们不需要包含在类中,因此您可以简单地这样做:

public delegate T Create<T>(T t);

public class MyClass<T>
{

    public void MyMethod(Create<T> create)
    {
         //...
    }
}

不需要静态 using 指令。这就是所有内置框架委托的定义方式:Func&lt;&gt;Action&lt;&gt; 等。

【讨论】:

  • +1。这是一个有效的替代方案,但它有其自身的权衡。现在,如果开发人员确实拥有完全限定的类型名称,则开发人员必须在以前没有的地方指定 &lt;T&gt;
  • 听起来我的问题的答案是“你不能这样做”,但@InBetween 为我确定了一种方法来重组此代码以解决我在代表周围的特定情况, 这是有价值的。您是否介意更新您的答案以直接解决问题(例如,如果我引用属性或方法而不是委托怎么办?),但保留其余部分,因为它确实回答了我的特定场景?
【解决方案2】:

简短的回答是不,我们不能这样做。

您不能编写带有泛型类型参数的 using 语句,其类型尚未可解析为具体类型或接口类型。

来自Microsoft Docs

泛型类,例如泛型简介中列出的 GenericList,不能按原样使用,因为它不是真正的类型;它更像是一种类型的蓝图。要使用 GenericList,客户端代码必须通过在尖括号内指定类型参数来声明和实例化构造类型。这个特定类的类型参数可以是编译器识别的任何类型。

所有T 参数都需要通过调用使用该泛型类型的代码来解析,并且在 using 语句的情况下,我们无法指定应替换哪种类型而不是泛型T 参数的任何方式。

您可以执行以下操作:using static MyNamespace.Delegates&lt;SomeType&gt;,但不是您想要执行的操作。我认为你需要坚持你在第一种方法中尝试的方法。

编辑: 快速搜索后,我找到了similar question here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-27
    • 2010-10-01
    • 2016-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    相关资源
    最近更新 更多