Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should a protected property in a C# child class hide access to a public property on the parent?

Tags:

c#

mono

I have the following code:

public class Parent {     public string MyField { get; set; } }  public class Child : Parent {     protected new int MyField { get; set; } } 

I try and access this with:

static void Main(string[] args) {     Child child = new Child();     child.MyField = "something"; } 

Visual studio 2008 compiles this without comment, but under Mono (2.4.2, Ubuntu) I get the error message

'HideTest.Child.MyField' is inaccessible due to its protection level (CS0122) 

Is one implementation or the other more compliant with the standard here?

Edit: Thanks to all the people who have pointed out the bad design. Unfortunately it's a third-party library and changing it significantly isn't practical.

like image 297
Tim Martin Avatar asked May 16 '10 20:05

Tim Martin


People also ask

What is protected property?

Protected property means personal property, the sale of which or prohibition against the sale of which is regulated by state or federal law.

What is a protected property C#?

C# Protected: Using the Protected Keyword in C# public means that your object's method can be called from anywhere, or that the instance variable that you declare public can be accessed from anywhere, whether outside or inside the class itself.

Why we are using protected in C#?

C# protected is used to allow derived classes access to base class properties and methods with the same name as long as those properties and methods are not private. As with other access modifiers, protected can be used with fields, properties and methods.

What is a protected field?

In many other languages there also exist “protected” fields: accessible only from inside the class and those extending it (like private, but plus access from inheriting classes). They are also useful for the internal interface.


2 Answers

From ECMA-334 (the C# spec) §10.7.1.2 :

A declaration of a new member hides an inherited member only within the scope of the new member.

You can see this behavior by running this test on Microsoft's implementation.

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;         }     } } 

Which will output:

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). 

So the property you're accessing from your Main() should be the base class property (as it is in MS.NET), not the derived property (as in Mono), because the new derived member only hides the 'old' base member in protected scope.

Mono is doing something wrong here according to the spec.

like image 57
Jason Punyon Avatar answered Oct 01 '22 21:10

Jason Punyon


Jason's answer is correct but he asks for a justification of this behaviour. (Namely that a hiding method is only hiding within the scope of the hiding method.)

There are a number of possible justifications. One in particular is that this is yet another way in which the design of C# mitigates the Brittle Base Class problem.

FooCorp makes Foo.DLL:

public class Foo {     public object Blah() { ... } } 

BarCorp makes Bar.DLL:

public class Bar : Foo {     // stuff not having to do with Blah } 

ABCCorp makes ABC.EXE:

public class ABC {     static void Main()     {         Console.WriteLine((new Bar()).Blah());     } } 

Now BarCorp says "You know, in our internal code we can guarantee that Blah only ever returns string thanks to our knowledge of our derived implementation. Let's take advantage of that fact in our internal code."

public class Bar : Foo {     internal new string Blah()     {         object r = base.Blah();         Debug.Assert(r is string);         return (string)r;     } } 

ABCCorp picks up a new version of Bar.DLL which has a bunch of bug fixes that are blocking them. Should their build break because they have a call to Blah, an internal method on Bar? Of course not. That would be terrible. This change is a private implementation detail that should be invisible outside of Bar.DLL.

like image 21
Eric Lippert Avatar answered Oct 01 '22 20:10

Eric Lippert