WolfOdrade
WolfOdrade

Reputation: 370

C# - Specify a struct field type from a generic interface

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

Answers (3)

Grax32
Grax32

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

supercat
supercat

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

Preston Guillot
Preston Guillot

Reputation: 6714

PrimeStruct also needs a generic parameter for this to work.

public struct PrimeStruct<T> : IData<T>, IBehavior

Upvotes: 1

Related Questions