开发一个通用接口我希望在接口中声明一个构造函数,但它说那里禁止构造函数。我试图声明一个静态工厂方法,但它说不允许使用静态方法,并建议使用'new'关键字。但我几乎不知道在C#中的接口内使用时,'new'关键字究竟意味着什么。你呢?
更新:
我没有发布任何示例代码,因为我不想混合2个问题 - 如何在界面中指定构造函数/工厂以及'new'关键字在接口中的含义。我甚至只被强制指定第一部分因为StackOverflow不接受纯粹形式的第二个问题,说它不符合质量标准。
但是,正如你所要求的那样,我将对我试图实现的目标进行抽样:
Interface IMyInterface <T, U, V>
{
IMyInterface (T, U, U);
// OR
static IMyInterface GetNewIMyInterface (T, U, U);
}
我只是希望每个派生类都实现这样的构造函数。
答案 0 :(得分:56)
Bala的回答是正确的,但看到为什么你想要这样做可能会有所帮助。考虑BCL设计人员在为CLR版本2设计库时遇到的问题。现有界面:
interface IEnumerable
{
IEnumerator GetEnumerator();
}
现在要添加:
interface IEnumerable<T> : IEnumerable
{
new IEnumerator<T> GetEnumerator();
}
新界面与返回类型中的旧界面不同。
你有什么选择?
1)将新的GetEnumerator标记为“new”,以便编译器知道这是一个新方法,它不会与同名但不同返回类型的旧方法冲突。
2)将名称更改为GetEnumerator2。
3)不要继承原始的IEnumerable。
选项2和3很糟糕。选项1非常棒:新的枚举可以与需要旧枚举的代码无缝协作,但编写为使用新枚举的代码默认情况下会获得“新的”通用行为。
答案 1 :(得分:26)
new
关键字告诉编译器您的定义隐藏了接口可能扩展的接口中包含的定义。
答案 2 :(得分:4)
您不能在接口中指定构造函数或静态方法... 可以做的是为泛型类型参数添加类型约束,例如
void Foo<T>() where T : new()
{
T t = new T();
// Do stuff with t
}
这就是你在想什么?
答案 3 :(得分:3)
接口应该指定合同。它只包含方法签名而不包含实现。接口不能直接实例化,因此接口中不允许使用构造函数。
http://msdn.microsoft.com/en-us/library/87d83y5b(v=vs.80).aspx
答案 4 :(得分:3)
您正在使用界面,但听起来您想要一个基类。接口永远不需要构造函数,因为它不能包含需要在构造函数中初始化的任何字段。我想你想要使用基类。
答案 5 :(得分:1)
首先,“ new”关键字实际上唯一要做的就是提示编译器不要产生警告,提示您应该使用“ new”关键字。除了消除警告之外,关键字本身也没有任何作用(在相关上下文中)。
现在,当您重新定义从其继承的接口中已经定义的成员(属性或方法)时,编译器希望您使用'new'关键字,并且这样做至少有两个可能的原因。首先,正如上面的Eric Lippert所提到的,您可能希望方法返回不同的类型(或使用不同的类型定义相同名称的属性)。另一种可能性是,如果要为两个接口定义不同的实现,则:
interface A
{
void a();
}
interface B : A
{
new void a();
}
class C : B
{
void A.a() { Console.WriteLine("Called by interface A!"); }
void B.a() { Console.WriteLine("Called by interface B!"); }
}
static class Test
{
public static void DoTest()
{
B b = new C();
b.a(); // Produces "Called by interface B!"
((A)b).a(); // Produces "Called by interface A!"
}
}
如果尝试在C中定义B.a()
而未在B中重新定义a()
,则会收到警告,提示它不是接口的成员:显式接口声明要求您使用接口成员已明确定义。
答案 6 :(得分:0)
C#和.NET不允许您在接口上声明构造函数。
这只是实现该接口的规定约束(请参阅.NET库中的ISerializable)。
如果你考虑一下,在接口上使用构造函数没有意义,因为你必须知道在调用构造函数时要创建的具体类。你将如何调用这样的接口构造函数,结果会是什么?