У меня есть абстрактный класс, который представляет неизменное значение.Как и строки, в неизменяемом классе есть методы, которые изменяют экземпляр, но на самом деле просто возвращают новый экземпляр с изменениями.Абстрактный класс имеет некоторые из этих методов, которые имеют поведение по умолчанию.Могу ли я иметь такой вид Создать измененный экземпляр и вернуть логику в абстрактный класс?Я вешаю трубку, потому что я не знаю, что положить в ???позиции.Кажется, мне нужен тип T, представляющий производный тип.Существуют ли какие-либо подобные схемы для преодоления этой проблемы?
public abstract class BaseImmutable
{
public readonly object Value;
protected BaseImmutable(object val)
{
Value = val;
}
public ??? ModifiyButNotReally()
{
object newValue = GetNewObjectFromOld(Value);
return new ???(newValue);
}
}
public class DerivedImmutable : BaseImmutable
{
public DerivedImmutable(object val) : base(val)
{
}
}
ОТВЕТ
Это оказалось проще, чем я подозревал.Метод можно сделать универсальным, не делая класс универсальным.Имея это в виду, единственное, что нам нужно сделать, - это ограничить универсальный аргумент для наследования от базового класса и требовать, чтобы он не был абстрактным путем включения ограничения new ().Последний шаг, который мне нужно было сделать, - это использовать отражение, чтобы получить конструктор без параметров для создания нового экземпляра.Я обнаружил, что это решение лучше, чем общий ответ класса, предложенный @Jason, который, как я узнал, известен как CURLYURURRING Template Pattern .Это также избавляет от необходимости создавать сложный для тестирования метод расширения / moq в отдельном статическом классе, как это предлагается @bottleneck.Тем не менее, ответ @ bottleneck - это то, что дало мне вдохновение для решения, поэтому баллы достаются ему.
public abstract class BaseImmutable
{
public readonly object Value;
protected BaseImmutable(object val)
{
Value = val;
}
public T ModifiyButNotReally<T>() where T : BaseImmutable, new()
{
object newValue = GetNewObjectFromOld(Value);
var ctor = typeof(T).GetConstructor(new[] { typeof(object) });
return (T)ctor.Invoke(new object[] { newValue });
}
}
public class DerivedImmutable : BaseImmutable
{
public DerivedImmutable(object val) : base(val)
{
}
}