从派生类重写公共属性

时间:2012-02-07 15:34:39

标签: c# inheritance override

在一个旧项目中,我们使用的是第三方程序集,其中的类具有包含一些硬编码信息的属性:

public string ConnectionString
{
    get
    {
        string[] fullDbName = new string[5];
        fullDbName[0] = "Data Source=";
        fullDbName[1] = this.dbServer;
        fullDbName[2] = ";Initial Catalog=";
        fullDbName[3] = this.FullDbName;
        fullDbName[4] = ";Integrated Security=SSPI;Pooling=false";
        return string.Concat(fullDbName);
    }
}

我需要能够自己构建连接字符串。所以我试图创建一个隐藏原始属性的派生类,但它似乎不起作用:

public class SqlServerRestorerExstension : SQLServerRestorer
{
    public SqlServerRestorerExstension(string dbServer, string dbName, string dbFilePath, string dbDataFileName, string dbLogFileName, bool detachOnFixtureTearDown, string connectionstring) : base(dbServer, dbName, dbFilePath, dbDataFileName, dbLogFileName, detachOnFixtureTearDown)
    {
        ConnectionString = connectionstring;
    }

    public string ConnectionString { get; private set; }
}

当我无法访问第三方代码时,是否可以以任何方式实现此目的?

4 个答案:

答案 0 :(得分:7)

正如其他人指出的那样,您可以使用new关键字隐藏基本成员属性。但请注意,这并不会将ConnectionString属性神奇地转换为多态函数,即如果您有类似这样的内容:

public class A 
{
    public string CString { get { return "a"; } }
}

public class B : A
{
    public new string CString { get { return "b"; }}
}

你这样做:

A a = new B();

Console.WriteLine(a.CString);

然后你仍会看到打印到控制台的“a”。事实上,new关键字只是阻止编译器发出有关隐藏基类成员的警告。它不会在运行时更改代码的行为。

您可以尝试使用装饰器模式并包装SQLServerRestorer,但如果这也不起作用,那我恐怕不行。

答案 1 :(得分:4)

您需要使用new

来表明您要“替换”此属性
public new string ConnectionString
{
   get { return "My custom connection string"; }
}

显然,您可以将其扩展为实现自己的set,即使只是为了利用自动实现的访问器。有关new的'版本控制'的文档可以找到here,但具体来说是:

  

使用new关键字告诉编译器您的定义隐藏了基类中包含的定义。这是默认行为。

答案 2 :(得分:3)

您正在寻找new关键字:

public class SqlServerRestorerExstension : SQLServerRestorer
{
    public SqlServerRestorerExstension(string dbServer, string dbName, string dbFilePath, string dbDataFileName, string dbLogFileName, bool detachOnFixtureTearDown, string connectionstring) : base(dbServer, dbName, dbFilePath, dbDataFileName, dbLogFileName, detachOnFixtureTearDown)
    {
        ConnectionString = connectionstring;
    }

    public new string ConnectionString { get; private set; }
}

答案 3 :(得分:0)

你想要override方法,但似乎你不能:

  

使用override修饰符修改方法,属性,索引器或事件。 override方法提供从基类继承的成员的新实现。由覆盖声明覆盖的方法称为重写的基本方法。重写的基本方法必须与覆盖方法具有相同的签名。

     

您无法覆盖非虚拟或静态方法。重写的基本方法必须是虚拟,抽象或覆盖。

虽然其他人指出您可以使用new修饰符,但我认为这不会对您有所帮助:

  

在同一个成员上同时使用new和override是错误的,因为这两个修饰符具有相互排斥的含义。 new修饰符创建一个具有相同名称的新成员,并使原始成员隐藏。 override修饰符扩展了继承成员的实现。

对我来说,这听起来像任何使用base(第三方)类型的代码都会调用旧属性 - 这只是等待发生的混乱!