tags:

views:

3969

answers:

5

This is probably not possible, but I have this class:

public class Metadata<DataType> where DataType : struct
{
    private DataType mDataType;
}

There's more to it, but let's keep it simple. The generic type (DataType) is limited to value types by the where statement. What I want to do is have a list of these Metadata objects of varying types (DataType). Such as:

List<Metadata> metadataObjects;
metadataObjects.Add(new Metadata<int>());
metadataObjects.Add(new Metadata<bool>());
metadataObjects.Add(new Metadata<double>());

Is this even possible?

+13  A: 
public abstract class Metadata
{
}

public class Metadata<DataType> : MetaData where DataType : struct
{
    private DataType mDataType;
}
leppie
Wow! I really didn't think that was possible! You're a life saver, man!
Carl
+6  A: 

Program to an interface not an implementation...

You will have the flexibility of doing what leppie said, but be able to easily add more types.

mson
+12  A: 

Following leppie's answer, why not make MetaData an interface:

public interface IMetaData { }

public class Metadata<DataType> : IMetaData where DataType : struct
{
    private DataType mDataType;
}
bruno conde
Can someone tell me why this approach is better?
Lazlo
Because no common functionality is shared - why waste a base class on that then? An interface is sufficient
flq
+2  A: 

Funny, I already have this in a personal library. There is a non-generic version as well as generic, using the new keyword:

public interface IMetadata
{
    Type DataType { get; }

    object Data { get; }
}

public interface IMetadata<TData> : IMetadata
{
    new TData Data { get; }
}

Explicit interface implementation is used to allow both Data members:

public class Metadata<TData> : IMetadata<TData>
{
    public Metadata(TData data)
    {
        this.Data = data;
    }

    public Type DataType
    {
        get { return typeof(TData); }
    }

    object IMetadata.Data
    {
        get { return this.Data; }
    }

    public TData Data { get; private set; }
}

You could derive a version targeting value types:

public interface IValueTypeMetadata : IMetadata
{

}

public interface IValueTypeMetadata<TData> : IMetadata<TData>, IValueTypeMetadata where TData : struct
{

}

public class ValueTypeMetadata<TData> : Metadata<TData>, IValueTypeMetadata<TData> where TData : struct
{
    public ValueTypeMetadata(TData data) : base(data)
    {}
}

This is just an example. The pattern can be extended to any kind of generic constraints.

Bryan Watts
A: 

Hi all,

why it is important that originally defined class:

public class Metadata where DataType : struct { private DataType mDataType; }

  1. is replaced with one derived from the same interface or abstract class is it maybe because IList<> members must share some common object type ?
  2. must that common type to have the same name as IList<> type, eg. IList -> derived from T, or IList -> derived from InterfaceT, IT ?

BR, Milan.

Milan