tags:

views:

56

answers:

5

Hi, I want to add some custom functionality to all my Controls AND my Forms. I have created a class MyControl, and there's no problem just doing:

MyControl : Control

and then letting my controls inherit from MyControl.

However, I want my forms to have the same functionality, and because Form inherits from ContainerControl, Scrollable Container, and THEN Control, I would have to create my own versions of all of these to make it use MyControl, which seems inefficient.

Is there any way around this? I can't use an interface, and I don't want to create a copy of the class called MyForm with the same functionality as MyControl

A: 

I think the only way to do it is with

MyForm : Form

Maybe use an interface plus extension methods to reduce code duplication as much as possible.

wefwfwefwe
+2  A: 

What you're looking for is either multiple inheritance (which doesn't exist in .net, with no plans to change that), or Default Interface Implementation, aka DII (which might exist in a future version of .net)

As of today, there's unfortunately no clean solution to this problem, and you best bet is to create two base classes. You can share the code in a third helper class, though, so that only the glue code is duplicated, not the actual implementation.

Depending on what functionality you're trying to achieve, another useful technique is to create a single class getting passed an object (either a Form or a Control) in its constructor, and adding the extra functionality you're wanting. However, you won't be able to access the control/form protected members in that way.

Here is a link discussing your issue.

Brann
Thanks. Actually I'm not looking for duplicate inhertitance, even though I have this problem right now Im glad that the Java/.NET creators chose to skip multi inheritance
Rolle
@Rolle : I'm curious to know why you're glad they skip it. If you're interested, here is what they did ti : http://blogs.msdn.com/csharpfaq/archive/2004/03/07/85562.aspx
Brann
I once had a very real encounter with the "diamond problem" in a larger C++ project, which kinda forced us rewrite a lot of code at a late stage. Generally, I think at some level your brain is bound to hurt when doing MI if you don't know very much how your app is going to look from the beginning, and I find you often don't.
Rolle
This kind of reasoning would lead to remove multithreading from the CLR (I once had a very real encounter with the "deadlock problem", which kinda forced us to write a lot of synchronization code... ". Once in a while (granted it's not that common), I end up writing ugly code to workaround the lack of MI in the CLR.
Brann
I disagree. There are a lot of reasonable alternatives to MI; threading is in my opinion something critical for many applications, and hard to live without.
Rolle
@Rolle : indeed ; but decrying MI because using it the wrong way can cause problem is the same as decrying MT for the same reasons.
Brann
A: 

If all you want to do is add extra methods, you can create extension methods which are methods that appear to be part of a certain object, but aren't.

You can declare one like this:

void MyMethod(this Control obj, string foobar);

You can then call this method as any other method of the Control class:

myButton.MyMethod("baz");

However, if you wish to override virtual methods, play with the internals of the class, etc. then there isn't much that I could help you with.

Charlie Somerville
+1  A: 

You don't have many choices here since multiple inheritance is not supported.

  1. Use extensions methods on Control

  2. Reimplement in MyForm what you did in MyControl.

For 2. you can make an interface, say IMyControl, and an helper class that implements it, like MyHelperControl : IMyControl. Then in MyControl and MyForm implements IMyControl but use a private MyHelperControl and maps all interface members to call of this helper, that way you only have one real code to manage.

interface IMyControl {
    void A();
}

class MyHelperControl : IMyControl {
    void A() {
        // your implementation here
    }
}

class MyControl : Control, IMyControl {
    private MyHelperControl _myHelper;
    void A() {
        _myHelper.A();
    }
}

class MyForm : Form, IMyControl {
    private MyHelperControl _myHelper;
    void A() {
        _myHelper.A();
    }
}
Julien Lebosquain
The question said he can't use an interface, although I don't see why he couldn't.
MusiGenesis
Maybe the "can't" was because an interface would me duplicate code? That's why I understood.
Julien Lebosquain
+1  A: 

One thing you can do is to have your forms inherit from a custom "master" form that contains an instance of MyControl, like this:

public partial class MasterForm : Form
{
    private MyControl _MyControl = new MyControl();

    public MasterForm()
    {
        InitializeComponent();
    }

    public void Method1()
    {
        _MyControl.Method1();
    }
}

This means duplicating all of MyControl's method signatures in MasterForm (or all the ones you need in your form, at least), but at least the method code itself would not be duplicated.

public partial class Form1 : MasterForm
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Method1();
    }
}

This approach avoids using an interface, although I'm curious as to why exactly you can't use an interface here.

MusiGenesis
@MusicGenesis : I think the OP can use an interface, but does want to avoid code duplication.
Brann
@Brann: well, he did say "I can't use an interface".
MusiGenesis
I meant that MyControl can't just be an interface, becasue it need to implement some code. Thanks for all the answers!
Rolle