40

我正在开发一组实现通用接口的类。我的库的使用者应该期望这些类中的每一个都实现一组特定的静态函数。无论如何我可以装饰这些类,以便编译器能够捕获其中一个函数未实现的情况。

我知道在构建消费代码时它最终会被捕获。而且我也知道如何使用一种工厂类来解决这个问题。

只是想知道是否有任何语法/属性需要类上的静态函数。

Ed删除了“接口”一词以避免混淆。

4

9 回答 9

35

不,C# 中没有对此的语言支持。我可以立即想到两种解决方法:

  • 在运行时使用反射;交叉手指和希望...
  • 使用单例/默认实例/类似来实现声明方法的接口

更新

实际上,只要您有单元测试,如果(像我一样)您来自严格的“静态类型”背景,第一个选项实际上并没有您想象的那么糟糕。事实是; 它在动态语言中运行良好。事实上,这正是我的通用运算符代码的工作方式——它希望你拥有静态运算符。在运行时,如果你不这样做,它会以适当的嘲弄语气嘲笑你......但它无法在编译时检查。

于 2009-02-23T14:16:43.483 回答
23

不,基本上听起来你在追求一种“静态多态性”。这在 C# 中不存在,尽管我提出了一种“静态接口”概念,它在泛型方面可能很有用

可以做的一件事是编写一个简单的单元测试来验证特定程序集中的所有类型是否符合您的规则。如果其他开发人员也将实现该接口,您可以将该测试代码放在某个公共位置,以便实现该接口的每个人都可以轻松地测试他们自己的程序集。

于 2009-02-23T14:21:55.217 回答
8

这是一个很好的问题,也是我在项目中遇到的一个问题。

有些人认为接口和抽象类的存在只是为了多态性,而不是为了强制类型实现某些方法。就个人而言,我认为多态性是主要用例,而强制实现是次要用例。我确实经常使用强制实现技术。通常,它出现在实现模板模式的框架代码中。基类/模板类封装了一些复杂的想法,子类通过实现抽象方法提供了许多变体。一个实用的好处是抽象方法为实现子类的其他开发人员提供了指导。Visual Studio 甚至可以为您存根方法。当维护开发人员需要在数月或数年后添加新的子类时,这尤其有用。

缺点是在 C# 中没有对其中一些模板方案的特定支持。静态方法就是其中之一。另一种是构造函数;理想情况下,ISerializable 应该强制开发人员实现受保护的序列化构造函数。

最简单的方法可能是(如前所述)使用自动化测试来检查静态方法是否在所需类型上实现。已经提到的另一个可行的想法是实现静态分析规则。

第三种选择是使用面向方面的编程框架,例如PostSharp。PostSharp 支持方面的编译时验证。您可以编写在编译时反映程序集的 .NET 代码,从而生成任意警告和错误。通常,您这样做是为了验证方面的使用是否合适,但我不明白为什么您也不能使用它来验证模板规则。

于 2009-07-22T20:30:24.170 回答
4

不幸的是,不,语言中没有这样的内容。

于 2009-02-23T14:12:22.167 回答
3

虽然对此没有语言支持,但您可以使用静态分析工具来强制执行它。例如,您可以为 FxCop 编写一个自定义规则,该规则检测类上的属性或接口实现,然后检查某些静态方法的存在。

于 2009-02-23T14:41:47.633 回答
1

单例模式并非在所有情况下都有帮助。我的例子来自我的一个实际项目。这不是人为的。

我有一个继承自第三方 ORM 中的类的类(我们称之为“Widget”)。如果我实例化一个 Widget 对象(因此在 db 中创建一行)只是为了确保声明了我的静态方法,那么我将比我试图清理的那个更混乱。

如果我在数据存储中创建这个额外的对象,我必须对用户、计算等隐藏它。

我在 C# 中使用接口来确保在一组类中实现通用功能。

实现这些功能的一些方法需要实例数据才能运行。我将这些方法编码为实例方法,并使用 C# 接口确保它们存在于类中。

其中一些方法不需要实例数据,因此它们是静态方法。如果我可以用静态方法声明接口,编译器可以检查这些方法是否存在于说它实现接口的类中。

于 2009-06-26T12:01:48.087 回答
0

不,这个功能没有意义。接口基本上是多重继承的缩小形式。它们告诉编译器如何设置虚函数表,以便可以在后代类中正确调用非静态虚方法。静态方法不能是虚拟的,因此,为它们使用接口是没有意义的。

于 2009-02-23T14:21:45.000 回答
0

正如 Marc Gravell 所建议的,使您更接近所需的方法是单例。

接口,除其他外,让您可以为您的类提供某种程度的抽象,这样您就可以使用给定的 API,而不管实现它的类型如何。但是,既然您确实需要知道静态类的类型才能使用它,那么为什么要强制该类实现一组函数呢?

也许您可以使用像 [ImplementsXXXInterface] 这样的自定义属性并提供一些运行时检查以确保具有此属性的类实际上实现了您需要的接口?

于 2009-02-23T14:57:15.867 回答
0

如果您刚刚收到这些编译器错误,请考虑以下设置:

  1. 在接口中定义方法。
  2. 用抽象声明方法。
  3. 实现公共静态方法,并让抽象方法覆盖简单地调用静态方法。

这是一些额外的代码,但你会知道何时有人没有实现所需的方法。

于 2011-11-04T21:14:25.703 回答