Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a C# Interface require or dictate a specific class?

Can I declare an Interface (i.e. IMySpecialControl) that requires classes implementing it to also inherit from some base class (i.e. System.Windows.Controls.UserControl)?

My thinking is that, no, this is not possible. But it would be really nice to write client code in such a way that it only takes a 'IMySpecialControl' which defines several members it cares about and it can count on that object also being a UserControl that it can then add to the GUI or manipulate.

I know that I can always check if the object instance defined as a 'IMySpecialControl' is also a UserControl, but I was hoping there might be some slick trick in .Net I'm not aware of. :-)

like image 632
Mel Green Avatar asked Dec 10 '13 17:12

Mel Green


2 Answers

Can I declare an Interface (i.e. IMySpecialControl) that requires classes implementing it to also inherit from some base class (i.e. System.Windows.Controls.UserControl)?

No, there's nothing in C# which defines that.

It would probably be simplest to create an abstract subclass of UserControl instead.

What you can do is have a generic method or type with a restriction that the type parameter implements an interface and is compatible with a class:

public void Foo<T>(T control) where T : UserControl, IMySpecialControl

I don't know whether that's helpful in your particular case, but it's the closest you can get to your original requirement.

like image 174
Jon Skeet Avatar answered Sep 30 '22 03:09

Jon Skeet


The short answer is no, Interfaces can't force a specific implementation - that goes against their definition. From MSDN:

An interface contains only the signatures of methods, properties, events or indexers.

In other words, a C# interface is defines how a class can be interacted with, not how the class acts. Why? Because C# doesn't want to support true Multiple Inheritance. Multiple inheritance, as the name implies, is when a class inherits from multiple classes. Think about if this was possible in C# - how do you resolve collisions of implementation? There would certainly be a couple benefits, but greater care would have to be taken when writing code.

Java introduced interfaces as a compromise between Single and Multiple Inheritance. In languages supporting multiple inheritance (C++), interfaces were common - but they weren't enforced by the compiler; instead an interface was an abstract class with only abstract methods, properties, etc. Because the pattern offered most of the benefits of multiple inheritance with virtually none of the risks, it was formalized (complete with syntax shortcuts) into what you are now familiar with.

So hopefully that sheds some light onto why you can't force implementation onto an interface. As Jon Skeet has pointed out, you are probably looking for an abstract class. Abstract classes can inherit from concrete (non-abstract) classes, which isn't really highlighted in the textbook examples of polymorphism. Your situation doesn't require an interface at all.

But, if you find yourself in a situation where you need an interface because the objects need to have different base classes, there is an alternative. Extension method(s) could make your life easier:

public interface IMySpecialControl
{
    string SpecialData { get; set; }
    int UniqueNumber { get; set; }
}

public static class MySpecialControlExtension
{
    public static string SpecialUniqueDataNumber(this IMySpecialControl control)
    {
        return control.SpecialData + control.UniqueNumber.ToString();
    }
}

public class Special : IMySpecialControl
{
    public string SpecialData { get; set; }
    public int UniqueNumber { get; set; }
}

This will enable any instance of IMySpecialControlExtension to call SpecialUniqueDataNumber with no parameters:

var specialInstance = new Special();
specialInstance.SpecialData = "Pi is exactly equal to: ";
specialInstance.UniqueNumber = 3;

// Note not passing a paramater for the instance to the extension method.
// It intentionally looks like a method of the class being extended,
//  both when reading the source and in intellisense.
Console.WriteLine(specialInstance.SpecialUniqueDataNumber()); 
like image 20
User Avatar answered Sep 30 '22 02:09

User