在C#中的界面内使用时,'new'关键字的含义是什么?

Iva*_*van 24 .net c# interface new-operator

开发一个通用的接口我希望在一个接口中声明一个构造函数,但它说那里禁止构造函数.我试图声明一个静态工厂方法,但它说不允许使用静态方法,并建议使用'new'关键字.但我几乎不知道在C#中使用界面时,'new'关键字究竟意味着什么.你呢?

更新:

我没有发布任何示例代码,因为我不想混合2个问题 - 如何在界面中指定构造函数/工厂以及'new'关键字在接口中的含义.II甚至只被强制指定第一部分因为StackOverflow不接受纯粹形式的第二个问题,说它不符合质量标准.

但是,正如你所要求的那样,我将对我试图实现的目标进行抽样:

Interface IMyInterface <T, U, V>
{
    IMyInterface (T, U, U);
    // OR
    static IMyInterface GetNewIMyInterface (T, U, U);
}
Run Code Online (Sandbox Code Playgroud)

我只是希望每个派生类都实现这样的构造函数.

Eri*_*ert 66

Bala的回答是正确的,但看看为什么要这样做可能会有所帮助.考虑一下BCL设计人员在为CLR版本2设计库时所面临的问题.现有的界面:

interface IEnumerable
{
  IEnumerator GetEnumerator();
}
Run Code Online (Sandbox Code Playgroud)

现在你要添加:

interface IEnumerable<T> : IEnumerable
{
  new IEnumerator<T> GetEnumerator();
}
Run Code Online (Sandbox Code Playgroud)

新界面与返回类型中的旧界面不同.

你有什么选择?

1)将新的GetEnumerator标记为"new",以便编译器知道这是一个新方法,它不会与同名但返回类型不同的旧方法冲突.

2)将名称更改为GetEnumerator2.

3)不要继承原来的IEnumerable.

选项2和3很糟糕.选项1非常棒:新的枚举可以与需要旧枚举的代码无缝协作,但编写为使用新枚举的代码默认情况下会获得"新的"通用行为.


Bal*_*a R 28

new关键字告诉编译器您的定义隐藏了接口可能扩展的接口中包含的定义.


Jon*_*eet 8

您不能在接口中指定构造函数或静态方法……您可以做的是为泛型类型参数添加类型约束,例如

void Foo<T>() where T : new()
{
    T t = new T();
    // Do stuff with t
}
Run Code Online (Sandbox Code Playgroud)

这是你想的吗?

  • @Ivan:好吧,你不能那样做。没有办法强制实现具有任何特定的构造函数。 (4认同)

M K*_*ter 5

首先,“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!"
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您尝试B.a()在 C 中定义而不a()在 B 中重新定义,您会收到一条警告,指出它不是接口的成员:显式接口声明要求您使用已显式定义成员的接口。