2015-03-06 2 views
0

Проблема, связанная с тем, как сделать мой SetContainer более общим, чтобы содержать любой тип, который расширяет CompoundValue. Это то, что я пробовал MapContainer<string, SetContainer<CompoundValue>>. Но im получает сообщение об ошибке state["a"] = new SetContainer<A>, говоря, что тип A не может быть явно преобразован в CompoundValue.Построение общих типов данных в C#

Я включил соответствующий пример, показывающий проблему ниже.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Data; 

using Microsoft.Modeling; // SetContainer and MapContainer 

namespace SGSN 
{ 
    class ControlState 
    { 
     MapContainer<string, SetContainer<CompoundValue>> state; 

     ControlState() 
     { 
      state = new MapContainer<string, SetContainer<CompoundValue>>(); 

      state["a"] = new SetContainer<A>(); //ERROR 
      state["b"] = new SetContainer<B>(); //ERROR 
      state["c"] = new SetContainer<C>(); //ERROR 
      state["d"] = new SetContainer<D>(); //ERROR 
     } 
    } 

    class A: CompoundValue 
    { 
     internal string a1; 
     internal string a2; 
     internal string a3; 
     internal string a4; 
     internal string a5; 
     internal string a6; 

     internal A(string a1, string a2, string a3, 
      string a4, string a5, string a6) 
     { 
      this.a1= a1; 
      this.a2= a2; 
      this.a3= a3; 
      this.a4= a4; 
      this.a5= a5; 
      this.a6= a6; 
     } 
    } 

    class B: CompoundValue 
    { 
     internal string b1; 
     internal string b2; 
     internal string b3; 

     internal B(string b1, string b2, string b3) 
     { 
      this.b1= b1; 
      this.b2= b2; 
      this.b3= b3; 
     } 
    } 

    class C: CompoundValue 
    { 
     internal string c1; 
     internal string c2; 
     internal string c3; 
     internal string c4; 
     internal string c5; 
     internal string c6; 
     internal string c7; 
     internal string c8; 

     internal C(string c1, string c2, string c3, 
      string c4, string c5, string c6, string c7, string c8) 
     { 
      this.c1 = c1; 
      this.c2= c2; 
      this.c3= c3; 
      this.c4= c4; 
      this.c5 = c5; 
      this.c6= c6; 
      this.c7= c7; 
      this.c8= c8; 
     } 
    } 

    class D: CompoundValue 
    { 
     internal string d1; 
     internal string d2; 
     internal string d3; 

     internal D(string d1, string d2, string d3) 
     { 
      this.d1= d1; 
      this.d2= d2; 
      this.d3= d3; 
     } 
    } 
} 
+0

1) Как объявляется тип SetContainer <>? 2) Правильный синтаксис: 'state [" a "] = новый SetContainer (); '(вы пропустили фигурные скобки) –

ответ

3

Вы можете объявить набор контейнер, как это:

public class SetContainer<T> 
    where T : CompoundValue 
{ ... } 

Однако это не решает проблему. Зачем? Вы можете использовать T, который происходит от CompoundValue (или CompoundValue); однако это не делает SetContainer<A> потоком SetContainer<CompoundValue>, даже если A происходит от CompoundValue. I., построенный общий тип не берет на себя отношение наследования его аргумента общего типа. Поэтому MapContainer<string, SetContainer<CompoundValue>> не принимает значение SetContainer<A>!

Давайте возьмем простой пример и давайте объявим список как этот

List<CompoundValue> list = new List<A>(); // Not possible! 

Это не представляется возможным, но давайте предположим, что это было. Теперь давайте добавим значения в список:

list.Add(new CompoundValue()); // Error! 
list.Add(new A());    // OK 
list.Add(new B());    // Error! 

Это представляется возможным, потому что A и B наследование от CompoundValue. Но помните, что список на самом деле List<A>, и этот список хочет A или потомков A для хранения. Ни CompoundValue, ни BA s!

+0

Im не создатель SetContainer – user3139545

+0

Это не имеет значения , То, что вы хотите, невозможно. –

1

Вы могли бы извлечь из SetContainer и определить ваше ограничение в производном class.Instead с помощью SetContainer то вы могли бы использовать производный класс с ограничением.

Итак, сначала вы должны определить свой вывод из SetContainer:

public class YourContainer<T> : SetContainer<T> where T : CompoundValue 
{ 
    // no code needed here 
} 

После этого, вы бы использовать контейнер везде вместо SetContainer:

MapContainer<string, YourContainer<CompoundValue>> state; 

Теперь вы можете inialize свой член с вашим контейнер:

state = new MapContainer<string, YourContainer<CompoundValue>>(); 

И вместо добавления SetContainer, теперь вы можете добавить свой Контейнер, который имеет ограничение типа.

state["a"] = new YourContainer<A>(); 
+0

Не могли бы вы расширить некоторые или предоставить ссылку на больший пример. Im a noob – user3139545

+0

Я обновил свой ответ, пожалуйста, дайте мне знать, если вам нужны подробности. – pgenfer

+0

Какой код должен быть в YourContainer? Могу ли я просто оставить его пустым, так как я хочу использовать только то, что находится в классе SetContainer? – user3139545

0

Что вы хотите сделать, невозможно. Даже если класс B происходит от A, это не означает, что Foo < B> совместим с Foo < A>.

Try компиляции этого:

class Foo<T> {} 
class Bar {} 
class Baz : Bar {} 

void Main() 
{ 
    var list = new List<Foo<Bar>>(); 
    list.Add(new Foo<Baz>()); 
} 

Вам нужно будет изменить свой дизайн. Попробуйте использовать класс-оболочку.

class Foo<T> 
{ 
    public T Item { get; set; } 
    public Foo(T t) 
    { 
     Item = t; 
    } 
} 

class Bar 
{ 
    public override string ToString() 
    { 
     return "Bar"; 
    } 
} 

class Baz : Bar 
{ 
    public override string ToString() 
    { 
     return "Baz"; 
    } 
} 

class BarHolder 
{ 
    public Bar BarItem { get; set; } 
    public BarHolder(Bar bar) 
    { 
     BarItem = bar; 
    } 
} 

void Main() 
{ 
    var wrappedBar = new BarHolder(new Bar()); 
    var wrappedBaz = new BarHolder(new Baz()); 

    var barList = new List<Foo<BarHolder>>(); 
    barList.Add(new Foo<BarHolder>(wrappedBar)); 
    barList.Add(new Foo<BarHolder>(wrappedBaz)); 

    foreach (var obj in barList) 
    { 
     Console.WriteLine(obj.Item.BarItem); 
    } 
} 
Смежные вопросы