Class generic property

Asked

Viewed 663 times

11

I have a class with two properties (Name and Value). The estate Name is a string, already the property Value I want to leave the variable type.

public class Field<TValue>
{
    public string Name { get; set; }
    public TValue Value { get; set; }

    public Field()
    {
    }

    public Field(string name, TValue value)
    {
        this.Name = name;
        this.Value = value;
    }
}

In this case it would be simple to instantiate this class with the desired type:

var field1 = new Field<int>("Nome1", 1);
var field2 = new Field<string>("Nome2", "Valor2");

The problem is I have an intermediate class that uses the class Field as property:

public class MyClass
{
    public string Prop1 { get; set; }
    public int Prop2 { get; set; }

    public Field<TValue>[] FieldArray { get; set; }
}

I mean, I want to be able to have a array of Field’s generic, but this last example is not valid for the compiler.

My ultimate goal is something like this:

var myClassObject = new MyClass();
myClassObject.Prop1 = "Teste";
myClassObject.Prop2 = 10;

myClassObject.FieldArray = new Field<TValue>[10];

myClassObject.FieldArray[0] = new Field<string>();
myClassObject.FieldArray[0].Name = "Field1";
myClassObject.FieldArray[0].Value = "Value1";

myClassObject.FieldArray[1] = new Field<int>();
myClassObject.FieldArray[1].Name = "Field2";
myClassObject.FieldArray[1].Value = 2;

Does language allow you to do something like that? What would be the right way?

  • Instead of TValue, wouldn’t it be better to use object?

  • 1

    @Felipeavelar no. never.

  • I wish I could force a stronger type. I think the object very subjective, but I believe it will be the way...

  • I understand you want to, the strongly typed type, the problem is that you want to vary this type within an array and this is problematic. Of course this will require some greater complexity in dealing with types, but, I imagine, within an array is not feasible...

  • 1

    @Jedaiasrodrigues You want the same instance of MyClass has arrays of Field with different types?

  • Exactly @LINQ ! Is it possible?

  • 1

    @Jedaiasrodrigues I’m not a great C#connoisseur, but I think this is not possible (at least not in the way you thought) because the types need to be known at compile time and this dynamism you need does not allow it.

  • @LINQ still thank you very much for your collaboration, I believe I will have to use object as @Felipeavelar commented.

  • 2

    Only a pitaco: between object and dynamic I would go from object, @Jedaiasrodrigues

Show 4 more comments

3 answers

9


In the case of having a property or any variable that needs to have different types, there is no way to keep the typing static and the genericity does not fit in this case, unless at least it can restrict a little, then it can vary, but always on top of a specific common type, you can do something.

As it seems that can any situation, have to use dynamic, found the most suitable for the case, but it may not be depending on the context, or object.

You need to analyze if you need it. Often the programmer thinks he needs it, but there may be another solution.

public class Program {
    public static void Main() {
        var myClassObject = new MyClass() { Prop1 = "Teste", Prop2 = 10, FieldArray = new Field<dynamic>[2] { new Field<dynamic>("f1", "v1"), new Field<dynamic>("f1", 1) } };
    }
}

public class Field<TValue> {
    public string Name { get; set; }
    public TValue Value { get; set; }

    public Field() {}

    public Field(string name, TValue value) {
        this.Name = name;
        this.Value = value;
    }
}

public class MyClass {
    public string Prop1 { get; set; }
    public int Prop2 { get; set; }
    public Field<dynamic>[] FieldArray { get; set; }
}

Behold working ideone. And in the .NET Fiddle. Also put on the Github for future reference.

  • A small addendum: Instead of using this class Field, the OP can use KeyValuePair<string, object>, that already exists in the framework.

8

Based on this response from Soen, you need to have a common base type to be able to "extend" these objects into collections. In the case of stringand int, the common base type will be, precisely, the object.

Then your code would look like this

public class Field
{
    public string Name { get; set; }
    public object Value { get; set; }

    public Field()
    {
    }

    public Field(string name, object value)
    {
        this.Name = name;
        this.Value = value;
    }
}

and class with Field:

public class MyClass
{
    public string Prop1 { get; set; }
    public int Prop2 { get; set; }

    public Field[] FieldArray { get; set; }
}

This should solve your problem and, if necessary, it is always possible to do the treatment to make the Value heavily typed.

6

What you requested can be done with dynamic or object.

Example:

public class Field<TValue>
{
    public string Name { get; set; }

    public TValue Value { get; set; }

    public Field()
    {
    }

    public Field(string name, TValue value)
    {
        this.Name = name;
        this.Value = value;
    }
}

public class MyClass
{
    public string Prop1 { get; set; }

    public int Prop2 { get; set; }

    public Field<dynamic>[] FieldArray { get; set; }
}

Utilizing:

    var x = new MyClass();
    x.FieldArray = new Field<dynamic>[5];

    x.FieldArray[0] = new Field<dynamic>();
    x.FieldArray[0].Value = "Teste";

    x.FieldArray[1] = new Field<dynamic>();
    x.FieldArray[1].Value = 1;

See working on .NET Fiddle

  • Why can only be done with Dynamic? object does not work for this case?

  • It works, I added the option. Thank you.

  • 1

    You are welcome, I am voting in favour now

Browser other questions tagged

You are not signed in. Login or sign up in order to post.