为什么接口不能指定静态方法?

42 c# static interface

我知道这个问题一直被问到,但我似乎无法找到足够好的答案.所以为了弄清楚我想知道的是什么,我将把它分成两个问题:

  1. 为什么接口不能有静态方法签名?我将尝试抢占非答案,询问为什么在世界上我想用以下内容执行此操作:我希望能够静态调用GetDbConnectionType()on SqliteCodeGeneratorMssqlCodeGenerator:

    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)
  2. 另一方面,这是第二个问题的问题,如果你知道一个很好的替代方案来实现上述目标,那么无论如何......

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.

我在博客上写了更多关于此的内容,但我怀疑这种好处并不能证明复杂性.

在替代方案方面 - 通常你会有另一个接口,并且有不同的类型来实现该接口.这在某些情况下效果很好,但在其他情况下则不然.

  • 此外,还有一个好处是强制类型实现静态成员,以及查询实现接口的类型,并且能够期望存在静态方法. (5认同)

Dea*_*bit 7

@JonSkeet:可以在CIL中创建一个静态接口成员,所以我担心你的第一个声明会产生误导.我认为它被C#作为设计选择而被省略,以鼓励正确使用接口.

获得此功能的最佳方法可能是使用扩展方法,这些方法允许您向接口的所有继承者或该接口的特定实现添加方法,但是您需要编写一个单独的类来保存扩展的实现(如果没有计划)的方法很容易失去踪迹.