2015-01-23 4 views
2

Я прихожу к C# от Java, и я не смог выяснить, как решить следующую проблему:Использовать общий базовый класс в коллекции классов, производных от общего

У меня есть общий базовый класс:

class MyBase<T> where T : SomeAncestorOfTs 
{ ... } 

, а затем несколько специализированных классов (A, B, C ...), полученные из него, как:

class A : MyBase<SomeSpecificT> 
{ ... } 

Сейчас где-то в моей трески e Я хотел бы создать Dictionary различных потомков MyBase: что-то вроде Dictionary<string,MyBase<>>, но это не работает.

Есть ли способ в C# кроме делать Dictionary<String,Object>?

В Java это было бы легко достигнуто путем выполнения HashMap<String,MyBase<? extends SomeAncestorOfTs>>.

UPDATE: T должен иметь общий базовый класс (SomeAncestorOfT).

ответ

4

Невозможно сделать это напрямую. Мое предложение было бы добавить еще один, не родовое, базовый класс:

class MyBase 
{ ... } 

class MyBase<T> : MyBase 
{ ... } 

А затем сделать словарь этой базы: Dictionary<string,MyBase>

+1

Я как раз собирался написать то же самое (хотя и с интерфейсом, а не с классом) +1. – petelids

+0

Я принял ваш ответ. Но есть одна вещь, которую я бы сказал, не разрешима: если общий базовый класс содержит абстрактный метод, который возвращает 'T' (и, следовательно, не может быть в неосновном базовом базовом классе), тогда я никогда не смогу его назвать (вызов словаря) без явного литья. – NumberFour

+0

@NumberFour Да, это правда. По крайней мере, для кода в «MyBase». Любой код вне этого класса знал бы, что 'T' в любом случае и может использовать' MyBase '. Так что это никогда не будет идеальным, но по крайней мере это не будет проблемой для остальной части кода, который использует эти классы. – Chris

0

Это, кажется, работает нормально, это вам поможет?

class Program 
{ 
    static void Main(string[] args) 
    { 
     Dictionary<string, MyBase> dic = new Dictionary<string, MyBase>(); 
     A<int> test= new A<int>(); 

     dic.Add("test", test); 
    } 
} 
class MyBase 
{ } 
class A<T> : MyBase 
{} 
+2

Попробуйте добавить экземпляр 'A' в этот словарь. – Chris

+0

Моя ошибка, я обновил ответ на рабочий код. –

+0

Nevermind, извините, я еще раз подумаю и обновил его. –

0
class MyBase<T> 
{ ... } 

class A : MyBase<SomeSpecificT> 
{ ... } 

, если вы не хотите использовать объект, вы можете использовать динамический.

var dict = new Dictionary<String, MyBase<dynamic>>(); 
+3

Это не то, что означает 'dynamic'. – Chris

+0

спасибо за указание, я не удалю сообщение, чтобы другие знали, что динамику не следует использовать. –

1

Короткий ответ не нет вы не можете сделать это в C# , MyBase<int> и MyBase<string> не имеют базового класса, кроме object. Лично я не вижу, что бы я сделал с ним, даже если он работал синтаксически.

Если все эти экземпляры имеют общее поведение, пусть все они реализуют этот интерфейс и имеют словарь этих.

+0

Эти экземпляры используют поведение (два метода), но один из методов возвращает T. – NumberFour

2

Как о чем-то вроде этого:

public class SuperBase 
{ 
} 

internal class MyBase<T> : SuperBase 
{ 
} 


internal class A : MyBase<string> 
{ 
    public void DoStuff() 
    { 
     Dictionary<string, SuperBase> _dict = new Dictionary<string, SuperBase>(); 

     _dict.Add("first", new MyBase<int>()); 
     _dict.Add("second", new MyBase<object>()); 
     _dict.Add("third", new MyBase<string>()); 
    } 
} 

Это не дает ошибку компиляции, как он стоит, по крайней мере (хотя я не могу гарантировать, что он не будет производить другие непредвиденные головные боли вниз по дороге).

Смежные вопросы