我正在开发一组实现公共接口的类。我的库的使用者应该期望这些类中的每一个都实现一组静态函数。无论如何,我可以装饰这些类,以便编译器能够捕获其中一个函数没有实现的情况。
我知道在构建消费代码时最终会被捕获。我也知道如何使用一种工厂类解决这个问题。
只是想知道是否有任何语法/属性要求在类上使用静态函数。
Ed 删除了“界面”一词以避免混淆。
答案 0 :(得分:30)
不,C#中没有语言支持。我可以立即想到两种解决方法:
(的更新强>)
实际上,只要你有单元测试,第一个选项实际上并不像你想象的那样(如我)你来自严格的“静态打字”背景。事实上;它在动态语言中运行良好。事实上,这正是我的generic operators代码的工作方式 - 它希望你有静态运算符。在运行时,如果你不这样做,它会以适当的嘲弄语气嘲笑你......但它无法在编译时检查。
答案 1 :(得分:18)
没有。基本上听起来像是在经历了一种“静态多态”之后。这在C#中不存在,尽管我提出了一种"static interface" notion which could be useful in terms of generics。
您可以做的一件事是编写一个简单的单元测试来验证特定程序集中的所有类型是否符合您的规则。如果其他开发人员也将实现该接口,您可以将该测试代码放入一些常见位置,以便实现该接口的每个人都可以轻松地测试他们自己的程序集。
答案 2 :(得分:6)
这是一个很好的问题,也是我在项目中遇到的问题。
有些人认为接口和抽象类只存在于多态,而不是强制类型实现某些方法。就个人而言,我认为多态性是主要用例,并强制实现次要。我经常使用强制实现技术。通常,它出现在实现模板模式的框架代码中。 base / template类封装了一些复杂的想法,子类通过实现抽象方法提供了许多变体。一个实用的好处是抽象方法为实现子类的其他开发人员提供了指导。 Visual Studio甚至可以为您存储方法。当维护开发人员需要在几个月或几年后添加新的子类时,这尤其有用。
缺点是C#中的某些模板方案没有特定的支持。静态方法是一种。另一个是构造函数;理想情况下,ISerializable应该强制开发人员实现受保护的序列化构造函数。
最简单的方法可能是(如前所述)使用自动化测试来检查静态方法是否在所需类型上实现。已经提到的另一个可行的想法是实现静态分析规则。
第三种选择是使用面向方面的编程框架,例如PostSharp。 PostSharp支持方面的编译时验证。您可以编写在编译时反映程序集的.NET代码,生成任意警告和错误。通常,您这样做是为了验证方面使用是否合适,但我不明白为什么您也不能使用它来验证模板规则。
答案 3 :(得分:4)
不幸的是,不,这种语言中没有这种内容。
答案 4 :(得分:3)
虽然没有语言支持,但您可以使用静态分析工具来强制执行。例如,您可以为FxCop编写一个自定义规则,用于检测类上的属性或接口实现,然后检查某些静态方法是否存在。
答案 5 :(得分:1)
单身模式在所有情况下都无济于事。我的例子来自我的实际项目。这不是人为的。
我有一个继承自第三方ORM中的类的类(我们称之为“Widget”)。如果我实例化一个Widget对象(因此在db中创建一行)只是为了确保我的静态方法被声明,我正在制造一个比我正在尝试清理的更糟糕的东西。
如果我在数据存储中创建这个额外的对象,我必须将其隐藏在用户,计算等之外。
我在C#中使用接口以确保在一组类中实现常用功能。
实现这些功能的一些方法需要运行实例数据。我将这些方法编码为实例方法,并使用C#接口确保它们存在于类中。
其中一些方法不需要实例数据,因此它们是静态方法。如果我可以使用静态方法声明接口,编译器可以检查这些方法是否存在于表示它实现接口的类中。
答案 6 :(得分:0)
不,这个功能没有意义。接口基本上是多重继承的缩小形式。它们告诉编译器如何设置虚函数表,以便可以在后代类中正确调用非静态虚方法。静态方法不能是虚拟的,因此,为它们使用接口毫无意义。
答案 7 :(得分:0)
正如马克·格拉维尔(Marc Gravell)建议的那样,让你更接近你需要的方法就是单身人士。
接口,除了其他功能之外,还允许您为类提供某种级别的抽象,这样您就可以使用给定的API,而不管实现它的类型如何。但是,由于您需要知道静态类的类型才能使用它,为什么要强制该类来实现一组函数?
也许您可以使用[ImplementsXXXInterface]之类的自定义属性并提供一些运行时检查以确保具有此属性的类实际实现您需要的接口?
答案 8 :(得分:0)
如果您刚刚收到编译器错误,请考虑以下设置:
这是一些额外的代码,但是你知道什么时候有人没有实现所需的方法。