Reputation: 370
In C#, is it possible to create a struct that does something like this?
I'm trying to vary the field size inside PrimeStruct without declaring _myField as an interface, just deferring from closing the IData declaration until the PrimeStruct is created.
I know WHY this doesn't work, but trying to find if someone has syntactic sugar for deferring type declaration of the contents of PrimeStruct to a contained generic type.
(Like PrimeStruct<T>
)
(no surprise: this does not compile)
interface IBehavior { void Foo(); }
interface IData<T> where T : IBehavior { }
struct MyStruct1 : IBehavior
{
public void Foo() { }
}
struct MyStruct2 : IBehavior
{
public void Foo() { }
}
//specifying an open type <T> here doesn't compile
public struct PrimeStruct : IData<T>, IBehavior
{
T _myField;
internal void SetData<T>(T value) where T : IBehavior
{
_myField = value;
}
public void Foo()
{
_myField.Foo();
}
}
public class Runner
{
public static void Main(string[] args)
{
PrimeStruct p = new PrimeStruct();
p.SetData(new MyStruct1());
p.Foo();
}
}
Or does this fall under the umbrella of the type not being known at compile time? I'm trying to avoid boxing the _myField struct value to an interface or resorting to HAllocGlobal.
Upvotes: 0
Views: 1133
Reputation: 4059
Like supercat said, it is not clear from this code what IData<T>
is for. If you take out the requirement that PrimeStruct
implement IData<T>
, and change _myField to an IBehavior
, then this will compile.
interface IBehavior { void Foo(); }
interface IData<T> where T : IBehavior { }
struct MyStruct1 : IBehavior
{
public void Foo() { }
}
struct MyStruct2 : IBehavior
{
public void Foo() { }
}
//specifying an open type <T> here doesn't compile
public struct PrimeStruct : IBehavior
{
IBehavior _myField;
internal void SetData<T>(T value) where T : IBehavior
{
_myField = value;
}
public void Foo()
{
_myField.Foo();
}
}
public class Runner
{
public static void Main(string[] args)
{
PrimeStruct p = new PrimeStruct();
p.SetData(new MyStruct1());
p.Foo();
}
}
As Preston Guillot said, you cannot have an non-generic class that inherits from an open generic (i.e. IData<T>
).
PrimeStruct : IData<int> // Non-generic inherits from closed generic is OK
PrimeStruct<T> : IData<T> // Open generic inherits from open generic is OK
PrimeStruct : IData<T> // Non-generic inherits from open generic will not compile
Upvotes: 1
Reputation: 81151
Since IData<T>
has no members, it's unclear what you're wanting the generic parameter for. If the intention is that IData<T>
should constrain T
to IBehavior
, and provide a means of getting and setting it, I would suggest that you have IData<T>
inherit from a non-generic IData
with a member of type IBehavior
; that method may provide a property getter, and a method to set the property, but the documentation for the method should make clear that most implementations of non-generic IData
will only accept certain implementations of IBehavior
.
Upvotes: 1
Reputation: 6714
PrimeStruct
also needs a generic parameter for this to work.
public struct PrimeStruct<T> : IData<T>, IBehavior
Upvotes: 1