2

为什么 re-sharper 希望我不要隐藏抽象类的属性?它希望我使用“新”,但这总是可取的吗?这似乎暗示隐藏变量以使用户无法执行 base.property 是一件坏事。

我只是对这个 OO 概念有点困惑,想知道是否有充分的理由支持或反对它。

我有

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

2 回答 2

5

MSDN 文档

尽管您可以在不使用 new 修饰符的情况下隐藏成员,但结果是警告。如果您使用 new 显式隐藏成员,它会抑制此警告并记录派生版本旨在作为替换的事实。

隐藏班级成员可能会导致误解和细微的错误。因此,编译器会警告您并要求您使用“new”修饰符明确隐藏可能有害的成员的意图。这可以防止意外隐藏基本类型成员而被忽视。

看看这个隐藏成员时问题如何潜入你的代码的小例子:

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

这将输出:

obj.Value = 11
((A) obj).Value = 5
((B) obj).Value = 11

光看Main方法的流程,你可能会认为在方法结束时obj.Value的值为16(=11+5)。但事实并非如此——更糟糕的是:根据您访问Value成员的方式,您会遇到不同的值。

现在,在这个小例子中,为什么在所有情况下输出都不相同而不是预期值的原因可能很容易快速发现。但是想象一下更大的软件项目有很多类,很多继承,方法参数是抽象基类或接口类型,第 3 方类库,你的名字......,隐藏成员引起的问题可能会变得更加难以解决确认。

于 2013-10-30T00:24:22.240 回答
2

如果您不希望外界能够访问 base.property,则应该对其进行保护。如果是,您不应该在派生类中重新定义它。如果它根本不应该对派生类可用,请将其设为私有。

它建议使用新的方法来防止歧义,但实际上你不应该一开始就在那里。

原因是如果我这样做:

var item = new verySpecificClass();
var val = item.commonProperty;

var basic = (baseClass)item;
if(val == basic.commonProperty)

我将得到与一个合理的程序员所期望的不同的结果。

于 2013-10-30T00:03:50.393 回答