Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Valid approach for generic operators

I have a class Gen<T> and I want to make it possible to compare them. The following code cannot be compiled, because the == cannot be applied to Parent and Child. Is there a way to make this comparison possible, or is this bad practice in general?

public class Parent{
    public int x;
}

public class Child:Parent{}

public class Gen<T> 
    where T : Parent 
{
    public T variable;
}

public static class Gen
{
    public static bool operator ==(Gen<Parent> left, Gen<Parent> right){
        if (left.variable.x == right.variable.x)
            return true;
        else
            return false;
    }
}

public void Test()
{
    Gen<Parent> foo = new Gen<Parent>();
    Gen<Child> bar = new Gen<Child>();

    if (foo == bar)
    {
        ...
    }
}

The full context is the following:

  1. Gen<T> equals ColorSet<T> where T:Color
  2. Parent equals Color
  3. Child is a class that stores additional information for a color, which are not necessary for every Color objects.

I want to access every Color through the ColorSet<T> class, which looks like this:

public class ColorSet<T> where T : Color
{
     private T blue;
     private T red;
     private T green;

     public ColorSet()
     {
         Red = (T)Activator.CreateInstance(typeof(T), new object[] { });
         Red.Name = Values.Res.get("red");
         Blue = (T)Activator.CreateInstance(typeof(T), new object[] { });
         Blue.Name = Values.Res.get("blue");
         Green = (T)Activator.CreateInstance(typeof(T), new object[] { });
         Green.Name = Values.Res.get("green");
     }
}

But sometimes I need ColorSet<Color> and sometimes ColorSet<Child> for the additional information. And it should be possible to compare ColorSet<Color> with ColorSet<Child> because they have the most relevant information in common.

like image 500
jasdefer Avatar asked Nov 23 '25 19:11

jasdefer


1 Answers

(expanding from the comments) A generic class doesn't seem to be necessary. A valid approach for getting operators to work for generic types is to re-work the types so that they're no longer generic.

ColorSet could be defined as

public class ColorSet {
  private Color red;
  private Color green;
  private Color blue;

  protected ColorSet(Type type) {
    red = (Color)Activator.CreateType(type);
    red.Name = Values.Res.get("red");
    green = (Color)Activator.CreateType(type);
    green.Name = Values.Res.get("red");
    blue = (Color)Activator.CreateType(type);
    blue.Name = Values.Res.get("red");
  }

  public static ColorSet FromType<T>() where T : Color {
    return new ColorSet(typeof(T));
  }
}

Instead of new ColorSet<ExtendedColor>(), you would now call ColorSet.FromType<ExtendedColor>().

This works so long as you don't actually need to use your T outside of your constructor.

If you had, for instance, a

public T Red { get { return red; } }

property, you would need to change that to a

public Color Red { get { return red; } }

property.

However, if you have anything like that, and you do want to keep the generic type, you can then put that in a derived generic class:

public class ColorSet<T> : ColorSet where T : Color {
  public ColorSet<T>() : base(typeof(T)) { }
  public new T Red { get { return (T)base.Red; } }
}

which still only needs operators for the base non-generic ColorSet class.