代码之家  ›  专栏  ›  技术社区  ›  ZzZombo

“virtual”修饰符对接口成员有什么影响?

  •  4
  • ZzZombo  · 技术社区  · 1 年前

    假设我有一个界面 interface IThing { virtual string A => "A"; } 。有什么效果 virtual 关键字在这里实现类型上有什么作用?令人惊讶的是,我在任何一个SO上都找不到任何关于这方面的信息, dotnet GitHub页面和讨论,也不在 learn.microsoft.com ,可能埋在所有不相关的内容下 interface 虚拟 以任何组合出现。从我的快速测试来看,它似乎没有任何明显的效果。我的直觉告诉我期望实现类的层次结构已经引入了给定的虚拟成员,就好像基本实现类已经自己声明了它们一样,但事实并非如此。

    例如

    class Thing: IThing
    {   
    }   
        
    class Thing2: Thing
    {
        override public string A => "!"; // ERROR: No suitable method found to override.
    }
    

    如果我声明 A 上的属性 Thing ,但不要显式声明它为虚拟的,它仍然不会编译。显然,我也可以自由地定义它们,不使用修饰符,尽管它存在于接口中并进行编译。和代码使用 IThing 只看到的默认实现 A. 不管我做什么,除非类直接实现接口,而不是通过此设置中的继承。

    有人能澄清一下的用途吗 虚拟 接口成员上的修饰符?我使用最新的C#稳定语言版本。

    1 回复  |  直到 1 年前
        1
  •  3
  •   Guru Stron    1 年前

    以下内容:

    interface IThing { virtual string A => "A"; }
    

    是这样叫的吗 default interface method 就我所见,虚拟实际上什么也没做,因为:

    这个 virtual 修饰符可以用于函数成员,否则该函数成员将是隐式的 虚拟

    也就是说,这只是一个明确的事实声明 界面 方法是虚拟的,因为语言团队决定不限制这些事情。

    另请参阅 Virtual Modifier vs Sealed Modifier 规范的一部分:

    决定:在LDM 2017-04-05中作出:

    • 非- 虚拟 应通过明确表示 sealed private .
    • 密封的 是使具有实体的接口实例成员为非的关键字- 虚拟
    • 我们希望允许接口中的所有修饰符
    • ...

    请注意,默认实现 IThing.A 不是的一部分 Thing ,所以你不能做 new Thing().A ,您需要先转换到接口。

    如果要覆盖 IThing。A. 在中 Thing2 那么您可以直接实现该接口:

    class Thing2: Thing, IThing
    {
         public string A => "!"; 
    }
    
    Console.WriteLine(((IThing)new Thing()).A); // Prints "A"
    Console.WriteLine(((IThing)new Thing2()).A); // Prints "!"
    

    另一种方式是宣布 public virtual string A 在中 事情 所以您当前的代码 减薄2 作品

    class Thing: IThing
    {
        public virtual string A => "A";
    }   
        
    class Thing2: Thing
    {
        public override string A => "!"; 
    }
    

    理解的含义 密封的 / 虚拟 标识符在itnerfaces中,您可以创建第二个接口:

    interface IThing {  string A => "A"; }
    interface IThing2 : IThing {  string IThing.A => "B"; }
    class Thing : IThing2 {}
    
    Console.WriteLine(((IThing)new Thing()).A); // Prints "B"
    

    而如果你申报 IThing。A. 密封的 然后 IThing2 将不会编译。

    还可以查看 why virtual is allowed while implementing the interface methods? 链接者 wohlstad 在评论中。