John L.
John L.

Reputation: 1953

Subclassing and generics in C#

I want to subclass a large number of classes so that they will all contain a certain set of the same properties. What would be the right way to do it in order to avoid repetition? I thought of using generics like:

public class SuperT<T> : T
{
    //the same set of properties
}

But the compiler says

Cannot derive from 'T' because it is a type parameter

EDIT: I am trying to subclass some classes in a third party assembly so I cannot use a base class.

For example, the types are "Image", "Label", "Button" etc and I want to subclass them all to contain a property like "Radius". (So that I would use SuperImage element in XAML and when I set it's Radius property from XAML, I will be able to run some certain logic.)

One other way I just thought of right now is using T4 templates. I wonder if there is a way to do this with generics without resorting to templates? I cannot understand why the compiler rejects it.

Upvotes: 0

Views: 1196

Answers (5)

Steve Fan
Steve Fan

Reputation: 3361

First of all, this might be a logical problem. What if you are going to extend a sealed class? Or Int32 class? Delegate?

Anyway, the way I recommend is to create an interface and implement all the functions you need in the subclass.

Upvotes: 0

Chase Florell
Chase Florell

Reputation: 47387

I don't think generics have anything to do with this, however inheritance is probably what you're looking for.

There are two types of inheritance that you can use to subclass, and extension methods work to "superclass"... sort of.

  1. Is-A inheritance
  2. Has-A inheritance
  3. And to simply add a similar method to a bunch of third party objects, you'll use an extension method.

Is-A inheritance

Use a base class if you've got similar method implementations.

public abstract class BaseFoo {

    public void Bar() {
         // actual code
    }
}

public class Foo : BaseFoo
{
}
var foo = new Foo();
foo.Bar();

Use an Interface if you need to implement the same method on each class.

public interface IFoo {
    void Bar();
}

public class Foo : IFoo {
    public override void Bar(){
        // bar implementation
    }
}
var foo = new Foo();
foo.Bar();

Combining the two is also allowed, but you can only inherit on base class, where you can inherit multiple interfaces.


Has-A inheritance

This is particularly useful with dependency injection, but it's simply the notion that you have an instance of another class to work with. It's essentially a wrapper class for you to work with.

public class Foo {
    private readonly ThirdPartyFoo _tpFoo;
    void Foo(ThirdPartyFoo tpFoo) {
        _tpFoo = tpFoo;
    }

    public void Bar(){
        // now I can do something with _tpFoo;
       _tpFoo.Bar(); 
    }
}
var tpFoo = new ThirdPartyFoo();
var foo = new Foo(tpFoo);
foo.Bar(); // invokes the underlying tpFoo

Lastly, if you just need to add a method to existing classes, then you create an extension method.

public static class ViewExtensions() 
{
    // this assumes your Image, Button, Label all inherit from View.
    public static Whatever Radius(this View view) {
        // do your radius work.
    }

}

Upvotes: 1

Igor
Igor

Reputation: 62213

If these classes all share a common base class or common interface you could write an extension method.

public static class ShapeExetnsionsExtLib
{
    public static double Radius(this ShapeBase shape){
        return /*calculate radious*/;
    }
}

From comments

I am trying to subclass some classes in a third party assembly so I cannot use a base class.

For example, the the types are "Image", "Label", "Button" etc and I want to subclass them all to contain a property like "radius".

Yes they share common base classes but I cannot add anything new to them.

Upvotes: 1

Abion47
Abion47

Reputation: 24671

In general, you want to use one of the answers already posted about using a base class and inheriting from that. However, if the classes are in a third party library and are marked as sealed, then you will need to create a wrapper class to use as a base class.

(Note that this option is a workaround and doesn't truly inherit from the third party class, so things in that class that are marked as protected won't be accessible without a liberal use of reflection.)

// The sealed class within another library
public sealed ThirdPartyClass
{
    public ThirdPartyClass(int i) { }

    public int SomeProperty { get; set; }

    public int SomeMethod(string val) { return 0; }

    public static void SomeStaticMethod() { }
}

// The wrapper class to use as a pseudo base class for ThirdPartyClass
public class BaseClass
{
    private ThirdPartyClass _obj;

    public BaseClass(int i) { _obj = new ThirdPartyClass(i); }

    public int SomeProperty
    {
        get { return _obj.SomeProperty; }
        set { _obj.SomeProperty = value; }
    }

    public int SomeMethod(string val) { return _obj.SomeMethod(val); }

    public static SomeStaticMethod() { ThirdPartyClass.SomeStaticMethod(); }
}

// The child class that inherits from the "base" BaseClass
public class ChildClass : BaseClass
{

}

Upvotes: 0

Rom
Rom

Reputation: 1193

Just Use a base class:

public class Base
{
    public int Id { get; set; }
    public string Name { get; set; }
}

And inherite from it:

public class A : Base
{

}

public class B : Base
{

}

Upvotes: 0

Related Questions