避免对具有非限定泛型类型的泛型静态类使用类名

Avoid using class name for generic static classes with unqualified generic types

提问人:Technetium 提问时间:1/5/2018 更新时间:1/5/2018 访问量:383

问:

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

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);
        }

    }

}

我很想去掉实现中的前缀,因为我相信它可以提高代码的可读性。通常,我已经通过 C# 6 中的“using static”指令删除了静态类作为前缀。但是在这种情况下,它不是“完全限定的类型名称”,因此我看不到实现这一目标的方法。我很想做一些类似以下示例的事情,但这并不像人们预期的那样工作。原因是因为在 的范围之外仍未定义。Delegates<T>.MyMethodTTMyClass

using static MyNamespace.Delegates<T>;

namespace MyNamespace {

    public class MyClass<T> {

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

    }

}

编译器也不允许我在类中移动“using static”指令。

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

使用 using 指令 C# 泛型

评论

0赞 15ee8f99-57ff-4f92-890c-b56153 1/5/2018
你要做的最好的事情就是制作非静态并继承它。但在单继承语言中,这似乎是一个坏主意。我不建议反思。就我个人而言,我会把它吸起来,忍受额外的打字和混乱。Delegates<T>
0赞 Sasha Alperovich 1/5/2018
Delegates 类必须是泛型的吗?

答:

1赞 Ehsan Sajjad 1/5/2018 #1

简短的回答是否定的,我们不能那样做。

不能使用泛型类型参数编写 using 语句,该参数的类型尚不可解析为具体类型或接口类型。

来自 Microsoft 文档

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

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

你可以做这样的事情:但不是你想做的事情。我认为你需要坚持你在第一种方法中尝试过的东西。using static MyNamespace.Delegates<SomeType>

编辑:快速搜索后,我在这里发现了一个类似的问题

3赞 InBetween 1/5/2018 #2

难道你不能简单地使非泛型,并使代表本身成为泛型吗?Delegates

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

现在应该在范围内:TMyClass<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)
    {
         //...
    }
}

无需静态使用指令。这是所有内置框架委托的定义方式:、 等。Func<>Action<>

评论

0赞 Technetium 1/5/2018
+1.这是一个有效的替代方案,但它有自己的权衡。现在,如果开发人员确实具有完全限定的类型名称,则开发人员必须指定以前他或她没有的位置。<T>
0赞 Technetium 1/5/2018
听起来我的问题的答案是“你不能这样做”,但@InBetween为我找到了一种方法来重组这段代码,以解决我围绕委托的特定情况,这很有价值。您是否介意更新您的答案以直接解决问题(例如,如果我引用的是属性或方法而不是委托怎么办?),但保留其余部分,因为它确实回答了我的特定场景?