Nicolai Schlenzig
Nicolai Schlenzig

Reputation: 882

Generic types and inheritance

I would like to be able to do the following for several classes:

var obj1 = new MyClass { Id = 1 };
var obj2 = new MyClass { Id = 2 };
obj1.Compare(obj2);

I made the following extension method (inspired by a different question inhere):

public static class ObjExt
{
    public static ICollection<string> Compare<T>(this T obj1, T obj2)
    {
        var properties = typeof(T).GetProperties();
        var changes = new List<string>();

        foreach (var pi in properties)
        {
            var value1 = typeof(T).GetProperty(pi.Name).GetValue(obj1, null);
            var value2 = typeof(T).GetProperty(pi.Name).GetValue(obj2, null);

            if (value1 != value2 && (value1 == null || !value1.Equals(value2)))
            {
                changes.Add(string.Format("Value of {0} changed from <{1}> to <{2}>.", pi.Name, value1, value2));
            }
        }
        return changes;
    }

Now, this works if I make a method in all classes I want to compare, so I figured I'd move it so a super class to DRY.

public class MyClass
{
    public int Id { get; set; }

    public ICollection<string> CompareMe<T>(T obj2)
    {
        return Compare<T>(obj2);
    }
}

If I move it to a super class, I get this compile error:

Cannot convert instance type argument 'SuperClass' to 'T'

If I do this in my super class:

return this.Compare<T>(obj2);

I get a compile error saying:

The type arguments for method 'Compare(T, T)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

How to make this generic in a super class?

Upvotes: 0

Views: 184

Answers (3)

Magnus
Magnus

Reputation: 46997

Not sure how your super class looks. But this compiles fine:

public class SuperClass
{
    public bool GenericTest<T>(T obj2)
    {
       return ObjExt.GenericTest(obj2, obj2);
    }
}

public class MyClass : SuperClass
{
    public int Id { get; set; }

    public bool SuperTest<T>(T obj2)
    {
        return this.GenericTest<T>(obj2);
    }
}

public static class ObjExt
{
    public static bool GenericTest<T>(this T obj1, T obj2)
    {
        return true;
    }
}

Upvotes: 1

Panos Rontogiannis
Panos Rontogiannis

Reputation: 4172

You can add a generic constraint on the SuperTest method:

public bool SuperTest<T>(T obj2) where T: SuperClass
            {
                return this.GenericTest(obj2);
            }

And replace T in the extensionmethod with SuperClass:

public static bool GenericTest(this SuperClass obj1, SuperClass obj2)
        {
            return true;
        }

I'm not sure if this is what you had in mind though.

Upvotes: 1

Christoffer
Christoffer

Reputation: 2125

This extension method:

public static bool GenericTest<T>(this T obj1, T obj2)
{
}

will not compile, because the compiler has no clue about what T really is: there is no context to infer types from. You either need to use something like where T: SuperClass or change the method parameters to this SuperClass obj1, SuperClass obj2.

Upvotes: 1

Related Questions