简体   繁体   中英

Generic Value Object in C#

I have a VO class that contains several variables incl. a variable that can be of different types and to prevent casting later on I wonder if I can make that class generic.

public class InputVO<T>
{
    public bool isEnabled;
    public T value;
}

Then I want to create an array of InputVOs and a method to get a typed InputVO...

public InputVO[] Inputs { get; private set; }

public InputVO GetInput(InputType type)
{
    return Inputs[(int)type];
}

How do I go about defining the array and the GetInput method so that they work with the generic InputVO? (The InputType type argument is an enum. Shouldn't really matter here, I think).

Generic type parameters are fixed at compile-time.
Whenever you use InputVO, that type parameter needs to be filled in.

  public InputVO<T1>[] Inputs { get; private set; }

But what you seem to want is different InputVO objects for each datatype, and to be able to retrieve them by type at runtime:

// Base class for all InputVOs
public abstract InputVOBase
{
    public bool isEnabled;
}

// InputVO for a specific data-type
public class InputVO<T> : InputVOBase
{
    public T Value;
}

Now you can use a dictionary from Type to InputVOBase.

  // One InputVO per datatype
  public Dictionary<Type, InputVOBase> AllInputs { get; private set; }

  // Return the VO for type T, or null
  public InputVO<T> GetInput<T>()
  {
      InputVOBase vo = AllInputs[typeof(T)];

      return (vo as InputVO<T>);
  }

You cannot create an array of a generic class without specifying the type. However, as you have control over the base type, you can make that implement a non generic interface and have a collection of that instead:

//Empty interface 
public interface IInputVO { }

//Your generic class now implements the interface
public class InputVO<T> : IInputVO
{
    public bool isEnabled { get; set; }
    public T Value { get; set; }
}

So now your array is of the interface type IInputVO :

IInputVO[] inputs = 
{ 
    new InputVO<int>(),
    new InputVO<string>(),
    new InputVO<SomeClass>(),
};

Cleaned up solution a bit. Mainly you need to collect your values in a dictionary.

void Main()
{
    var a = new InputVO<string> { Value = "test" };
    var b = new InputVO<int> { Value = 5 };
    Inputs.Add(typeof(string), a);
    Inputs.Add(typeof(int), b);

    var x = GetInput<string>();
    Console.WriteLine(x.Value);
    var y = GetInput<int>();
    Console.WriteLine(y.Value);
}

public abstract class InputVOBase
{
    public bool isEnabled;
}

public class InputVO<T> : InputVOBase
{
    public T Value;
}

public Dictionary<Type, InputVOBase> Inputs = new Dictionary<Type, InputVOBase>();

public InputVO<T> GetInput<T>()
{
    return Inputs[typeof(T)] as InputVO<T>;
}

Thanks for the tips anyone! Phew, since there's no way getting around casting and I only need to regard a couple of types I think all the generics-based solutions are a bit overkill in my case. So I simply added casted getters to my VO ...

public class InputVO
{
    public bool isEnabled;
    public bool isValid;
    public InputType type;
    public object value;

    public int IntValue { get { return (int)value; } }
    public float FloatValue { get { return (float)value; } }
    public bool BoolValue { get { return (bool)value; } }
    public Vector2 Vector2Value { get { return (Vector2) value; } }
    public Vector3 Vector3Value { get { return (Vector3)value; } }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM