【发布时间】:2020-08-12 03:11:06
【问题描述】:
考虑以下代码:
using System;
namespace Sample
{
public interface IGetOptions
{
string Options { get; }
}
public interface ISetOptions
{
string Options { set; }
}
public interface IOptions : IGetOptions, ISetOptions
{
}
public class MyOptions : IOptions
{
public string Options { get; set; }
}
public class Program
{
public static void Main(string[] args)
{
var a = new MyOptions();
DoIt(a);
Console.WriteLine(a.Options);
}
private static void DoIt(IOptions x)
{
x.Options = "test"; // Ambiguity between IGetOptions.Options and ISetOptions.Options
}
}
}
我一直将属性理解为返回值或分配值的方法的语法糖。鉴于IGetOptions 和ISetOptions 之间的冲突只存在于名称上,并且每个接口都定义了get 或set,为什么编译器不能解决上面的歧义?
对我来说,很明显应该在这里调用ISetOptions.set_Options。如果我按如下方式更改代码,一切都会正常编译:
public interface IGetOptions
{
string Options();
}
public interface ISetOptions
{
void Options(string value);
}
public interface IOptions : IGetOptions, ISetOptions
{
}
public class MyOptions : IOptions
{
public string Options() { return _options; }
public void Options(string value) { _options = value; }
private string _options;
}
public class Program
{
public static void Main(string[] args)
{
var a = new MyOptions();
DoIt(a);
Console.WriteLine(a.Options());
}
private static void DoIt(IOptions x)
{
x.Options("test");
}
}
这就是我一直理解的在属性的底层发生的事情,那么为什么编译器不能为我做这个跳转呢?
我也意识到(我认为)一种解决方法是使用new 关键字来隐藏继承的属性。使用我发布的第一个代码 sn-p,对 IOptions 的以下更改使代码编译并按预期工作:
public interface IOptions : IGetOptions, ISetOptions
{
new string Options { get; set; }
}
这对我来说也很好奇。当然,我从来没有故意使用new 来隐藏继承的属性或方法,但我认为这意味着IOptions.Options 在物理上与IGetOptions.Options 不同,这意味着接受IGetOptions 并评估Options 的方法不会看到如果同一对象也是IOptions,则与IOptions.Options 相同。所以这里的问题是:为什么编译器足够聪明,可以折叠和关联在名称上发生冲突的继承属性,但又不够聪明,无法解决上述歧义?
提前致谢,如果有任何需要澄清的地方,请告诉我。
【问题讨论】:
-
我明白你的意思,但为什么还要设计这样的东西呢?通常,当您不控制接口并且存在名称冲突时,您会显式地实现一个。即使编译器会处理歧义,您的代码在其他人看来仍然是模棱两可的。
-
这并不像选择你认为最适合这种情况的那样简单,编译器有一套非常复杂的成员查找规则,你可以在规范中看到它@ 987654338@ 碰巧这种情况属于最后一个要点“否则,查找不明确,并发生绑定时错误。”是的,他们当然可以指定解决这个问题的方法,但是他们没有。可能是这违反了其他规则,或者复杂性超过了好处,或者他们只是不能被打扰,也许@EricLippert 可以跳到这里
标签: c# inheritance interface compiler-construction