views:

71

answers:

1

My tiny mind can't come up with an elegant solution to this problem. Suppose I have class such as this:

    public class Foo<T>
    {
        public RecordType Type { get; set; }
        public T Value { get; set; }
    }

Where RecordType may look something like this:

 public enum RecordType
    {
        EmptyRecord,
        BooleanRecord,
        IntegerRecord,
        StringRecord,
        ByteRecord
    }

The goal is to treat an IEnumerable<Foo<T>> uniformly for an iteration and/or to switch on the RecordType and perform an action while avoiding boxing the intrinsic types if at all possible. In addition, it would be nice to use a factory to create these Foo's off of a factory method.

I've fumbled with a few quick implementations of commonality in base class or interface and nothing I came up with answered this, seemingly, very simple problem elegantly.

Small edit: I should've mentioned that my primary goal is to use the .Value without forcing a cast on the caller.

+1  A: 

You could introduce a non-generic interface IFoo:

public interface IFoo
{
    RecordType Type { get; set; }
}

which is implemented by the generic Foo class:

public class Foo<T> : IFoo
{
    public T Value { get; set; }
}

and create a factory method that creates a Foo instance depending on RecordType:

public static IFoo CreateFoo(RecordType type)
{
    switch (type)
    {
        case RecordType.Bool: return new Foo<bool>();
        // ...
    }
}

Once you've created a Foo instance this way, you can't access the value yet, because you don't know the type parameter yet. But you can check for the type using the Type property and do the appropriate cast:

IFoo foo = CreateFoo(RecordType.Bool);

if (foo.Type == RecordType.Bool)
{
    Foo<bool> boolFoo = (Foo<bool>)foo;
    bool value = boolFoo.Value;
}

If you have a method that works with Foo objects, for example:

void DoIt<T>(IEnumerable<Foo<T>> foos)
{
    foreach (Foo<T> foo in foos)
    {
        Qux(foo.Value);
    }
}

and have an enumerable of IFoo objects, you can Cast/OfType that:

IEnumerable<IFoo> foos = // ...
DoIt<bool>(foos.OfType<Foo<bool>>());

So, essentially, you use Foo<T> when you know T at compile-time, and IFoo if you know T only at run-time. IFoo requires a check to turn it into a Foo<T> for some T at run-time.

dtb
Thanks for the answer. I came up with a variation of this earlier and couldn't abstract away coercing the `IFoo`'s into `Foo<T>`'s for a caller either. At any given time that I have created, through factory, a collection of `IFoo`'s I require the caller to either know T and get a subset or in the iteration body switch on Type to cast into a Foo<T>. I think I want to bend this static language too far. Thanks for confirming my suspicion! Perhaps I should've originally asked, what is the better way to do this. =)
Marc