Я столкнулся с ситуацией, когда я хочу, чтобы Deal class знал об этом DealDetail type, и наоборот, я хочу, чтобы DealDetail знал о Deal type. В будущем я хочу иметь много потомков Deal и DealDetails.
Я пытался реализовать его с помощью дженериков, но он не хочет компилироваться. компилятор выдает ошибку: не удается неявно преобразовать тип Program.ConcreateDeal в TDeal
public static void Main()
{
Console.WriteLine("Hello World");
var deal = GetDeal<ConcreateDeal,ConcreateDealInfo>();
}
public static TDeal GetDeal<TDeal, TDealInfo>()
where TDeal : DealBase<TDeal, TDealInfo>
where TDealInfo : DealInfoBase<TDeal, TDealInfo>
{
return new ConcreateDeal();
}
public class DealBase<TDeal, TDealInfo>
where TDeal : DealBase<TDeal, TDealInfo>
where TDealInfo : DealInfoBase<TDeal, TDealInfo>
{
public TDealInfo DealInfo {get; set;}
}
public class ConcreateDeal : DealBase<ConcreateDeal, ConcreateDealInfo> {}
public class DealInfoBase<TDeal, TDealInfo>
where TDeal : DealBase<TDeal, TDealInfo>
where TDealInfo : DealInfoBase<TDeal, TDealInfo>
{
public TDeal Deal {get; set;}
}
public class ConcreateDealInfo : DealInfoBase<ConcreateDeal, ConcreateDealInfo> { }
Я ожидал, что в методе GetDeal<ConcreateDeal,ConcreateDealInfo>() тип ConcreateDeal будет приведен к базе Deal type неявно, через наследование, но это не так. Где я не прав?
dotnetfiddle: https://dotnetfiddle.net/sjtxTC
хм .. кажется разумным. Спасибо.





Ошибка компилятора здесь:
public static TDeal GetDeal<TDeal, TDealInfo>()
where TDeal : DealBase<TDeal, TDealInfo>
where TDealInfo : DealInfoBase<TDeal, TDealInfo>
{
return new ConcreateDeal(); // <== compiler error
}
Вы предоставляете общие аргументы, которые указывают, что возвращаемый тип должен быть DealBase<TDeal, TDealInfo>. Вы можете написать любое количество классов, унаследованных от DealBase и DealInfoBase, и тогда метод может быть вызван с универсальными аргументами, не соответствующими ConcreteDeal.
Это немного сложнее увидеть из-за огромного количества общих аргументов. Вот более простая версия с менее общими аргументами для иллюстрации. Так проще, но это то же самое.
public class Dog : Animal { }
public class Cat : Animal { }
public class Animal
{
public static TAnimal GetAnimal<TAnimal>()
{
return new Dog();
}
}
Это не будет компилироваться по той же причине.
Общий аргумент говорит, что метод вернет TAnimal. Итак, если вы позвоните
var cat = Animal.GetAnimal<Cat>();
тип возврата должен должен быть Cat. Но как есть метод вернет Dog. Это не имеет смысла, поэтому компилятор предотвращает это.
Думаю, я понял. В случае универсального метода с типом возврата, являющимся универсальным параметром, тело метода не может возвращать конкретную реализацию. Спасибо за объяснение
Иногда ошибки компилятора с дженериками бывают странными и кажутся неправильными. Но они всегда мешают вам делать то, что не сработает. Часто сбивает с толку выяснение того, что не так, что вам мешает.