Есть ли способ использовать свойство с тем же именем, но имеет различный тип в производном классе?

У меня есть устаревший код с использованием BaseClass, и код ожидает, что clientid будет иметь тип int. Затем у меня есть требование создать новый класс DerivedClass, который очень похож на BaseClass, но теперь customerid должен быть строкой. Унаследованный код не может быть изменен, поэтому тестирование не требуется.

Как получить эффект, который я хочу использовать наследование (или любым другим способом)?

Ниже приведен пример тестового кода Linqpad, который я должен сделать. Очевидно, что он не будет компилироваться, потому что clientid в DerivedClass должен быть int. Мне нужно свойство string, называемое customerid. Это должно быть это имя, потому что другой код будет использовать этот класс вместо BaseClass и ожидает, что одно и то же свойство будет иметь строку типа.

public  class  BaseClass
{
    public virtual int customerid {get; set;}

    public void printname()
    {
       customerid = 1;
       customerid.Dump();
    }
}

public class DerivedClass : BaseClass
{
    public override string customerid {get; set;}

    public void PrintCustomerID()
    {
        customerid = "jshwedeX"; 
        customerid.Dump();
    }
}



void Main()
{
    DerivedClass dc = new DerivedClass();
    dc.printname();
}

Ответ 1

Вы можете использовать модификатор new следующим образом:

public class BaseClass
{
    public virtual int customerid {get; set;}

    public void printname()
    {
       customerid = 1;
       customerid.Dump();
    }
}

public class DerivedClass : BaseClass
{
    public new string customerid {get; set;}

    public void PrintCustomerID()
    {
        customerid = "jshwedeX"; 
        customerid.Dump();
    }
}

Это даст вам желаемые результаты, но также будет скрывать свойство в базовом классе. Если вы указали экземпляр DerivedClass как переменную BaseClass, вы могли бы только ссылаться на свойство в базовом классе; а не производный класс.

Другими словами:

BaseClass instance = new DerivedClass();
string customerId = instance.customerid; // <- this won't compile

Альтернативой будет использование явных реализаций интерфейса:

public interface IBase
{
    int customerid { get; set; }
}

public interface IDerived
{
    string customerid { get; set; }
}

public class Derived : IBase, IDerived
{
    int IBase.customerid { get; set; }
    string IDerived.customerid { get; set; }
}

Когда ваш экземпляр Derived хранится в переменной типа IBase, customerid будет разрешен к версии int, а когда она будет сохранена в переменной типа IDerived, она решит к версии string:

var derived = new Derived();
IBase ibase = derived;
IDerived iderived = derived;
int id1 = ibase.customerid; // <- compiles just fine
string id2 = iderived.customerid; // <- compiles just fine

Вы также можете использовать кастинг:

var instance = new Derived();
int id1 = ((IBase)instance).customerid;
string id2 = ((IDerived)instance).customerid;

Имейте в виду, что явные реализации интерфейса заставляют реализованные члены не быть видимыми, если только переменная не имеет тип интерфейса:

var instance = new Derived();
var customerid = instance.customerid; // <- this won't compile