Не существует неявного референтного разговора от T до TBase <ChildBase> - PullRequest
1 голос
/ 07 декабря 2011

У меня есть два разных класса, происходящих из одного базового класса.Каждый из них имеет коллекцию, производную от другого базового класса, но различного производного класса.

class MasterA : MasterBase<ClientA>
class MasterB : MasterBase<ClientB>

public class MasterBase<ClientClass> where ClientClass : ClientBase
{
    public List<ClientClass> Clients;
} 

Class ClientA : ClientBase
Class ClientB : ClientBase

Class ClientBase

Я хочу иметь UserControl, который работает с родительскими / дочерними списками обоих Master / Client любого типа (A или B).

public class Test<MasterClass> where MasterClass : MasterBase<ClientBase>
{
    GenericRepository<MasterClass> repo = new GenericRepository<MasterClass>();
    MasterClass master = repo.GetAll;
    // do some changes to (base fields of) the master collection and its client collection !
    repo.SaveOrUpdate(master);
}

Но .... я не могу создать экземпляр этого класса Test ..

var t = new Test<MasterA>();
>> There's no implicit reference conversation from MasterA to MasterBase<ClientBase>

Итак, есть ли способ изменить класс Test, чтобы иметь возможность делатьчто я указал?был бы очень признателен за некоторые советы.

Ответы [ 2 ]

2 голосов
/ 08 декабря 2011

Не зная, с какими ограничениями вы работали, изначально разместил это как комментарий.

Будет ли

public class Test<MasterClass,U> where MasterClass : MasterBase<U> where U: ClientBase

подходящим изменением вашей кодовой базы?Очевидно, что эта строка также должна измениться:

var t = new Test<MasterA,ClientA>();

Проблема заключается в том, что только из-за наличия отношений наследования между двумя классами X и Y это не означает, что общий типтипы G<X> и G<Y> имеют одинаковые (или любые) отношения наследования.Так что MasterBase<ClientA> не не наследуется от MasterBase<ClientBase>

2 голосов
/ 07 декабря 2011

Вы пытаетесь перейти от более конкретного универсального к менее конкретному универсальному, чтобы нарушить безопасность типов.

Я изменил ваши типы для представления Кошек и Собак, надеюсь, это продемонстрирует проблему:

void Main()
{

    Test<AnimalList<Animal>> t = new Test<CatList>();
    t.List.Add(new Cat());
    //You just dogged a cat!
    t.List.Add(new Dog());

    //Change your t to something like:
    Test<AnimalList<Animal>> t = new Test<AnimalList<Animal>>();
    t.List.Add(new Cat());
    //You just dogged an *animal* that's perfectly ok!
    t.List.Add(new Dog());
}

public class Test<TAnimalList> where TAnimalList : AnimalList<Animal>
{
    public TAnimalList List { get; set; }
}

public class CatList : AnimalList<Cat> {}
public class DogList : AnimalList<Dog> {}

public class AnimalList<TAnimal> : List<TAnimal> where TAnimal : Animal
{
} 

public class Cat : Animal 
{
    public override void Speak() { "Meow".Dump(); }
}
public class Dog : Animal
{
    public override void Speak() { "Woof".Dump(); }
}

public abstract class Animal 
{
    public abstract void Speak();
}

Возвращаясь к вашему примеру, если компилируется (хотя я не знаю, если вы этого хотите), если вы измените его на:

var t = new Test<MasterBase<ClientBase>>();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...