Как перегрузить преобразование типов в обобщённом абстрактном классе?
Нужно добавить перегрузку преобразований в обобщённый абстрактный класс чтобы все наследники реализовали эту перегрузку. Что примерно я пытаюсь сделать:
abstract class AStat<T> where T:AStat<T>
{
public int Value { get; set; }
public static implicit operator T (int x) // метод перегрузки преобразования типов
{
return new T{ T.Value = x };
}
}
class S1 :AStat<S1> // класс наследник
{
}
Как видно получается масло масленое при объявлении класса AStat.
Данный код не работает по причине "Тип Tв методе перегрузке преобразования типов не считается типом AStat".
Пытался явно преобразовать T в AStat
return new (AStat<T>)T{ Value = x };
Опять масло масленое и тоже не помогает
Пытался сделать так:
{
return new (T)AStat<T>{ Value = x };
}
Безрезультатно
Я понимаю что данную проблему можно решить просто написав в каждом наследнике метод перегрузки преобразования типов или просто написать не париться вовсе на счёт перегрузки преобразования типов, но хотелось бы узнать как такую проблему можно решить "красивым" путём
Ответы (2 шт):
Вы почти все правильно сделали, нужно было лишь добавить условие для типа T - у него должен быть конструктор без параметров. Также, в перегрузке оператора в качестве возвращаемого типа должен выступать AStat<T> Получаем следующее:
abstract class AStat<T> where T : AStat<T>, new()
{
public int Value { get; set; }
public static implicit operator AStat<T>(int x)
{
return new T {Value = x};
}
}
class S1 : AStat<S1>
{
}
Использование:
var s1 = (S1) 4; // s1.Value теперь равно 4
Первая ошибка, которую выдает студия - возможное отсутствие конструктора у типа T.
Для решения, необходимо добавить соответствующее ограничение new ()
class AStat<T> where T : AStat<T>, new()
Следующая ошибка указывает на то, что при пользовательских переопределениях преобразований типов, нужно использовать ближайший тип. В данном случае это не T, а AStat<T>
public static implicit operator AStat<T>(int x)
И наконец последняя ошибка: некорректное использование конструктора с блоком инициализации.
Внутри блока нужно обращаться непосредственно к полю
return new T { Value = x };
После исправления ошибок, код вполне рабочий:
abstract class AStat<T> where T : AStat<T>, new()
{
public int Value { get; set; }
public static implicit operator AStat<T>(int x) // метод перегрузки преобразования типов
{
return new T { Value = x };
}
}
class S1 : AStat<S1> // класс наследник
{
}
S1 t = (S1)10; // вернет нужный тип с заполненным свойством `Value`