Reputation: 7374
The problem im having is how to make my SetContainer
more generic to contain any type that extends CompoundValue
.
This is what I have tried MapContainer<string, SetContainer<CompoundValue>>
.
But im getting an error on state["a"] = new SetContainer<A>
saying that the type A can not be explicitly converted to CompoundValue.
I have included a relevant example showing the problem below.
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;
}
}
}
Upvotes: 0
Views: 111
Reputation: 112279
You could declare the set container like this:
public class SetContainer<T>
where T : CompoundValue
{ ... }
However this does not solve the problem. Why? You can use a T
that derives from CompoundValue
(or CompoundValue
itself); however, this does not make SetContainer<A>
a descendant of SetContainer<CompoundValue>
, even if A
derives from CompoundValue
. I.e., the constructed generic type does not take over the inheritance relation of its generic type argument. Therefore a MapContainer<string, SetContainer<CompoundValue>>
does not accept a SetContainer<A>
as value!
Let's take a simpler example and let's declare a list like this
List<CompoundValue> list = new List<A>(); // Not possible!
This is not possible, but let's assume it was. Now let's add values to the list:
list.Add(new CompoundValue()); // Error!
list.Add(new A()); // OK
list.Add(new B()); // Error!
This seems to be possible because A
and B
inherit from CompoundValue
. But remember, the list is in reality a List<A>
and this list wants A
or descendants of A
to be stored. Neither CompoundValue
nor B
are A
s!
Upvotes: 3
Reputation: 16352
What you want to do is not possible. Even if a class B derives from A, it doesn't mean that Foo<B> is compatible with Foo<A>.
Try compiling this:
class Foo<T> {}
class Bar {}
class Baz : Bar {}
void Main()
{
var list = new List<Foo<Bar>>();
list.Add(new Foo<Baz>());
}
You will need to change your design. Try using a wrapper class.
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);
}
}
Upvotes: 0
Reputation: 622
Your could derive from SetContainer and define your constraint in your derived class.Instead of using a SetContainer then you could use your derived class with the constraint.
So first you would define your derivation from SetContainer:
public class YourContainer<T> : SetContainer<T> where T : CompoundValue
{
// no code needed here
}
After that, you would use your container everywhere instead of the SetContainer:
MapContainer<string, YourContainer<CompoundValue>> state;
Now you can inialize your member with your container:
state = new MapContainer<string, YourContainer<CompoundValue>>();
And instead of adding a SetContainer, you can now add your Container which has the type constraint defined.
state["a"] = new YourContainer<A>();
Upvotes: 1