我知道这个问题已经被问了个遍,但我似乎无法找到足够好的答案。 因此要清楚什么,我想知道,我会在这两个问题分开这样的:
为什么不能接口具有静态方法的签名? 我会尽力抢占非答案,询问为什么在世界上我想用下面这样做:我会希望能够以静态调用GetDbConnectionType()
上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"; } }
在另一方面,这是第二个问题的事情,如果你知道一个很好的选择,通过各种手段达到上述目标,那么...
假设你可以在一个界面,一个类型必须有一个特定的静态方法指定...你会怎么称呼呢? 多态性致力于通过实例 -而静态成员明确不使用的情况。
现在,话虽如此,有一种情况中,我可以看到静态接口成员的工作:泛型类型。 例如:
// This isn't valid code...
public void Foo<T>() where T : ICodeGenerator
{
string type = T.GetDbConnectionType();
}
这将呼吁具体类型的静态成员T
。
我的博客上更多关于这个 ,但我怀疑的利益并不能证明的复杂性。
在替代方面 - 通常你有另一个接口,并有不同的类型,以实现该接口。 行之有效在某些情况下,而不是在别人。
@JonSkeet:这是可能的创建CIL静态接口成员 ,所以我怕你的第一个说法是误导。 我认为它是从C#省略设计选择由微软团队鼓励接口正确用法。
得到这个功能最好的办法可能是使用扩展方法 ,这些都会让你的方法添加到您的接口的所有继承或特定的实现该接口的,但是你需要编写一个单独的类来保存扩展的实现这(如果没有计划)方法可以很容易失去联络。
乔恩的回答涵盖了几乎一切,所以我的答案只有包括可能的工作,周围用.NET配置API。 这需要一点语法的开销,但它确实给你实例静态访问。
interface IStorage
{
void Store(string item);
}
static class Storage
{
private static readonly IStorage _instance;
static Storage()
{
var storageTypeString = ConfigurationManager.AppSettings["storageTypeString"];
var storageType = Type.GetType(storageTypeString, true);
_instance = (IStorage)Activator.CreateInstance(storageType);
}
public static void Store(string item)
{
_instance.Store(item);
}
}
这可能有点帮助,如果一个接口可以指定一个静态类,使得类的成员会被编译器为接口的静态成员才能看到。 因此,代替具有使用静态类Enumerable<T>
以获得Enumerable<T>.Default
,人们可以代替句法指定IEnumerable<T>.Default
。
这将是更有益的,如果一个接口可以指定一些这样的静态方法应该是类似于扩展方法一个时尚可用,但没有与他们(相关怪异的作用域规则,所以接口可能出现以提供多个“方便”过载一些成员函数,而不需要所有的实施方式的,以提供它们)。
这将是非常有益的,如果,有这样的功能组合,接口方法可以宣布“可选”,这样,当实现提供了一种方法,将被使用,而当它没有扩展十岁上下的方法将被自动取代。 这可能会需要改变CLR,但是。
在任何情况下,由于接口不包括静态类,最好可以做的是提供静态类的接口的用户会发现有用的,即使编译器就会把这些类和接口,完全独立的实体。
我知道这是旧的,但实际上,你可以在一个静态类的名称空间之外声明静态函数。
但他们的方式你把它,你只想让功能静态的抽象类
从你做这个接口做
public static class Interfacefunction{
public static string GetDbConnectionType(this ICodeGenerator me)
{
// this is the method I would like to be static:
// you can even get access to me
return "SQLiteConnection";
}
}
A排序变通办法的(尽管它实际上可能是更好的这种方式),为了这个,我已经决定使用是使用静态实例,而不是一个静态的接口。
而不是:
// does not compile
ISomeInterface {
static void DoSomething();
static bool TestSomething(string pValue);
// etc...
}
static class SomeStaticClass : ISomeInterface {
public static void DoSomething() {
}
public static bool TestSomething(string pValue) {
}
}
定义一个类(使它通用如果逻辑必须在你使用它的类之间会发生变化):
sealed class SomeClass {
public void DoSomething() {
// reusable implementation
}
public bool TestSomething(string pValue) {
// reusable implementation
}
}
并给这个类的静态实例,以您的静态类:
static class SomeStaticClass {
static readonly SomeClass sSomeClass = new SomeClass();
}
唯一的问题是,你必须决定是否将财产暴露在静态实例:
static class SomeStaticClass {
static readonly SomeClass sSomeClass = new SomeClass();
public static SomeClass SomeProperty { get { return sSomeClass; } }
}
...
SomeStaticClass.SomeProperty.DoSomething();
if (SomeStaticClass.SomeProperty.TestSomething(someValue))
...
或包裹它的方法:
static class SomeStaticClass {
static readonly SomeClass sSomeClass = new SomeClass();
public static void DoSomething() {
sSomeClass.DoSomething();
}
public static bool TestSomething(string pValue) {
sSomeClass.TestSomething(pValue);
}
}
...
SomeStaticClass.DoSomething();
if (SomeStaticClass.TestSomething(someValue))
...