2010-11-09 2 views
4

Я хочу создать расширяемую вложенную структуру, и кажется, что я должен сделать это с помощью дженериков, хотя я не могу использовать их «правильно».Расширение использования C# generics?

Я хочу, чтобы иметь возможность создавать дочерние классы из GroupType и/или OptionType. Проблема в том, что я не могу выполнить операцию new для общих типов, хотя я указал, что они могут быть только определенного базового типа.

Есть ли способ сделать то, что я пытаюсь сделать?

public class AllInfo<GroupType, OptionType> 
    where GroupType: GroupBase<OptionType> 
    where OptionType: OptionBase 
{ 
    public List<string> Names { set; get; } 
    public List<GroupType> Groups { set; get; } 

    public AllInfo() 
    { 
     DataSet ds = DatabaseRetreival(); 
     this.Groups.add(new GroupType(ds["Name"], ds["Type"])); 
    } 

} 

public class GroupBase<OptionType> 
    where OptionType: OptionBase 
{ 
    public string Name { set; get; } 
    public string Type { set; get; } 
    public List<OptionType> Options { set; get; } 

    public GroupBase(string name, string type) 
    { 
     this.Name = name; 
     this.Type = type; 

     DataSet ds = DatabaseRetreival(this.Type); 
     this.Options.Add(new OptionType(ds["Name"])); 
    } 
} 

public class OptionBase 
{ 
    public string Name { set; get; } 

    public OptionBase(string name) 
    { 
     this.Name = name; 
    } 
} 

ответ

2

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

Единственный конструктор, который вы можете потребовать это конструктор без параметров:

where GroupType: GroupBase<OptionType>, new() 

Поскольку это только позволяет вам использовать конструктор без параметров, вы также можете использовать виртуальный метод для ввода данных в объекте, например, :

GroupType group = new GroupType(); 
group.Init(ds["Name"], ds["Type"]); 
this.Groups.add(group); 
+0

Удивительный, спасибо! –

4

Вы должны указать классы, которые должны иметь конструктор по умолчанию.

where GroupType: GroupBase<OptionType>, new() 

Посмотреть this article и прыгайте вниз к разделу Общие ограничения.

+0

Это не поможет, так как он не использует конструктор без параметров. – Guffa

+1

Ах, нет ограничений для конструкторов с несколькими параметрами, хотя есть статья, с которой я столкнулся, используя lambdas, к которой можно было бы использовать. http://www.ademiller.com/blogs/tech/2007/11/an-alternative-to-the-c-generic-new-constraint/ –

+0

Это помогло спасибо –

1

Компилятор не может этого допускать, поскольку он не может гарантировать, что у OptionType есть конструктор с правильной подписью. Но вы можете передать фабричную функцию вместо того, чтобы вызывать конструктор непосредственно:

public class Foo<T> 
{ 
    private List<T> myObjects; 

    public Foo(Func<string, T> factory)) 
    { 
     myObjects = new List<T>(); 
     foreach (string s in GetDataStrings()) 
      myObjects.Add(factory(s)); 
    } 
} 

Так что если у вас есть Bar класс с конструктором принимает строку, вы делаете это:

Func<string,Bar> barFactory = x => new Bar(x); 
var foo = new Foo<Bar>(barFactory); 
0

проблема вы в foundationally основы в очень больших количествах класса связи, которые вы пытаетесь смягчить с наследованием/дженерик. Я предлагаю вам пересмотреть, почему вы считаете, что это необходимо. Этот квест в конечном итоге приведет вас к интерфейсам, сервисному программированию и IoC, например, Ninject или Castle Windsor.

Однако, если вы хотите быстро исправить, что еще больше увеличивает сложность кода (потому что у вас нет сложных вариантов здесь, кроме изменения вашей философии кодирования), используйте абстрактный/виртуальный метод, возможно, назовите его Bind(), вместо конструкторов.

[полужирным для ТЛ, д-р]