Why does re-sharper want me to not hide a property from an abstract class?
It wants me to use 'new', but is that always preferable?
It seems to imply that hiding a variable so the user can't do base.property is a bad thing.
I'm just a little confused about this OO concept and was wondering if there were strong reasons for or against it.
I have
public abstract class baseClass{
protected string commonProperty {get; set;}
}
public abstract class moreSpecificBaseClass : baseClass {
// Resharper would prefer I use 'new' below
protected string commonProperty = "Some specific setting";
}
public class verySpecificClass : moreSpecificBaseClass {
// Some code
}
From the MSDN documentation:
Although you can hide members without the use of the new modifier, the
result is a warning. If you use new to explicitly hide a member, it
suppresses this warning and documents the fact that the derived
version is intended as a replacement.
Hiding class members can lead to misunderstandings and subtle errors. Hence the compiler warns you and requires you to make your intention of a possibly harmful member hiding explicit by using the "new" modifier. This prevents an accidental hiding of a base type member from being unnoticed.
See this little example of how problems can sneak into your code when hiding members:
public abstract class A
{
public int Value = 0;
}
public class B : A
{
// This hides the Value member from the base type A
public new int Value = 0;
}
static void SetValue(B obj, int value)
{
obj.Value = value;
}
static void AddToValue(A obj, int value)
{
obj.Value += value;
}
static void Main(string[] args)
{
B obj = new B();
SetValue(obj, 11);
AddToValue(obj, 5);
Console.Out.WriteLine("obj.Value = " + obj.Value);
Console.Out.WriteLine("((A) obj).Value = " + ((A) obj).Value);
Console.Out.WriteLine("((B) obj).Value = " + ((B) obj).Value);
}
This will output:
obj.Value = 11
((A) obj).Value = 5
((B) obj).Value = 11
Just by looking at the flow of the Main method, you might think that at the end of the method the value of obj.Value is 16 (=11+5). But it isn't - it is even worse: depending on how you access the Value member you will encounter different values.
Now, in this small example, the reason(s) of why the output is not the same and not the expected value in all cases might be easy and quickly to spot. But imagine larger software projects with many classes, lots of inheritances, method arguments being of abstract base class or interface types, 3rd-party class library, you name it..., and the problems caused by hidden members might become much more difficult to identify.
If you don't want the outside world to be able to access the base.property, it should be protected. If it is, you shouldn't be redefining it in a derived class. If it shouldn't be available to the derived class at all, make it private.
It's suggesting new to prevent ambiguity, but in reality you shouldn't be there to begin with.
The reason is that if I do this:
var item = new verySpecificClass();
var val = item.commonProperty;
var basic = (baseClass)item;
if(val == basic.commonProperty)
I'm going to get different results than what a reasonable programmer would expect.