我有以下代码:
public class Parent
{
public string MyField { get; set; }
}
public class Child : Parent
{
protected new int MyField { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我试着通过以下方式访问:
static void Main(string[] args)
{
Child child = new Child();
child.MyField = "something";
}
Run Code Online (Sandbox Code Playgroud)
Visual Studio 2008编译时没有注释,但在Mono(2.4.2,Ubuntu)下我收到错误消息
'HideTest.Child.MyField' is inaccessible due to its protection level (CS0122)
Run Code Online (Sandbox Code Playgroud)
一个实现或其他更符合标准吗?
编辑:感谢所有指出糟糕设计的人.不幸的是,它是第三方库,并且显着地改变它是不实际的.
Jas*_*yon 25
来自ECMA-334(C#规范)§10.7.1.2:
新成员的声明仅在新成员的范围内隐藏继承的成员.
您可以通过在Microsoft的实现上运行此测试来查看此行为.
using System;
using NUnit.Framework;
namespace ScratchPad
{
[TestFixture]
public class Class1
{
[Test]
public void InheritanceHiding()
{
var b = new Base();
var d = new Derived();
var baseSomeProperty = b.SomeProperty;
var derivedSomeProperty = d.SomeProperty;
b.GetSomeProperty();
d.GetSomeProperty();
}
}
public class Base
{
public string SomeProperty
{
get
{
Console.WriteLine("Getting Base.SomeProperty");
return "Base.SomeProperty";
}
}
public string GetSomeProperty()
{
return SomeProperty;
}
}
public class Derived : Base
{
protected new int SomeProperty
{
get
{
Console.WriteLine("Getting Derived.SomeProperty");
return 3; //Determined by random roll of the dice.
}
}
public new int GetSomeProperty()
{
return SomeProperty;
}
}
}
Run Code Online (Sandbox Code Playgroud)
哪个会输出:
Getting Base.SomeProperty //(No Controversy)
Getting Base.SomeProperty //(Because you're calling from public scope and the new member is in protected scope, there is no hiding)
Getting Base.SomeProperty //(No Controversy)
Getting Derived.SomeProperty //(Now because you're calling from protected scope, you get the protected member).
Run Code Online (Sandbox Code Playgroud)
因此,您从中访问的属性Main()应该是基类属性(在MS.NET中),而不是派生属性(如在Mono中),因为新派生成员仅隐藏受保护的"旧"基本成员范围.
根据规范,Mono在这里做错了.
Eri*_*ert 18
杰森的回答是正确的,但他要求对这种行为进行辩解.(即隐藏方法仅隐藏在隐藏方法的范围内.)
有许多可能的理由.特别值得一提的是,这是C#设计减轻脆性基类问题的另一种方式.
FooCorp制作Foo.DLL:
public class Foo
{
public object Blah() { ... }
}
Run Code Online (Sandbox Code Playgroud)
BarCorp制作Bar.DLL:
public class Bar : Foo
{
// stuff not having to do with Blah
}
Run Code Online (Sandbox Code Playgroud)
ABCCorp制作ABC.EXE:
public class ABC
{
static void Main()
{
Console.WriteLine((new Bar()).Blah());
}
}
Run Code Online (Sandbox Code Playgroud)
现在BarCorp说:"你知道,在我们的内部代码中,我们可以保证Blah只返回字符串,这要归功于我们对派生实现的了解.让我们在内部代码中利用这个事实."
public class Bar : Foo
{
internal new string Blah()
{
object r = base.Blah();
Debug.Assert(r is string);
return (string)r;
}
}
Run Code Online (Sandbox Code Playgroud)
ABCCorp选择了一个新版本的Bar.DLL,它有一些阻止它们的bug修复.他们的构建是否应该打破,因为他们调用了Blah,Bar上的内部方法?当然不是.那太可怕了.此更改是一个私有实现细节,应该在Bar.DLL之外不可见.
| 归档时间: |
|
| 查看次数: |
2480 次 |
| 最近记录: |