我知道这个问题一直被问到,但我似乎无法找到足够好的答案.所以为了弄清楚我想知道的是什么,我将把它分成两个问题:
为什么接口不能有静态方法签名?我将尝试抢占非答案,询问为什么在世界上我想用以下内容执行此操作:我希望能够静态调用GetDbConnectionType()
on SqliteCodeGenerator
和MssqlCodeGenerator
:
interface ICodeGenerator
{
// this is the method I would like to be static:
string GetDbConnectionType();
}
abstract class CodeGeneratorBase : ICodeGenerator
{
public abstract string GetDbConnectionType();
public void GenerateSomeCode(StringBuilder s)
{
s.AppendLine("var foo = new " + GetDbConnectionType() + "();");
}
}
class SqliteCodeGenerator : CodeGeneratorBase
{
public override string GetDbConnectionType()
{
return "SQLiteConnection";
}
}
class MssqlCodeGenerator : CodeGeneratorBase
{
public override string GetDbConnectionType()
{
return "SqlConnection";
}
}
Run Code Online (Sandbox Code Playgroud)另一方面,这是第二个问题的问题,如果你知道一个很好的替代方案来实现上述目标,那么无论如何......
Jon*_*eet 65
假设您可以在接口中指定类型必须具有特定的静态方法...您将如何调用它?多态性通过实例工作 - 而静态成员显式不使用实例.
现在,已经说过,有一种情况我可以看到静态接口成员工作:泛型类型.例如:
// This isn't valid code...
public void Foo<T>() where T : ICodeGenerator
{
string type = T.GetDbConnectionType();
}
Run Code Online (Sandbox Code Playgroud)
这将调用具体类型的静态成员T
.
我在博客上写了更多关于此的内容,但我怀疑这种好处并不能证明复杂性.
在替代方案方面 - 通常你会有另一个接口,并且有不同的类型来实现该接口.这在某些情况下效果很好,但在其他情况下则不然.
@JonSkeet:可以在CIL中创建一个静态接口成员,所以我担心你的第一个声明会产生误导.我认为它被C#作为设计选择而被省略,以鼓励正确使用接口.
获得此功能的最佳方法可能是使用扩展方法,这些方法允许您向接口的所有继承者或该接口的特定实现添加方法,但是您需要编写一个单独的类来保存扩展的实现(如果没有计划)的方法很容易失去踪迹.
归档时间: |
|
查看次数: |
38757 次 |
最近记录: |