20

Similar to this Java question. I would like to specify that a variable implements multiple interfaces. For instance

private {IFirstInterface, ISecondInterface} _foo;

public void SetFoo({IFirstInterface, ISecondInterface} value)
{
    _foo = value;
}

Requirements:

  • I don't have the ability to add an interface to most type that would be passed in to Foo. So I can't create a third interface that inherits from IFirstInterface and ISecondInterface.
  • I would like to avoid making the containing class generic if possible because the type of Foo doesn't have much to do with the class and the user isn't likely to know it at compile time.
  • I need to use foo to access methods in both interfaces at a later time.
  • I would like to do this in a compiler safe way, i.e. no trying to cast to the interface just before trying to use it. If foo does not implement both interfaces quite a bit of functionality won't work properly.

Is this possible?

Edit: I've wanted this a few times for various reasons. In this instance it's because I am changing a set of properties from ObservableCollections to ReadOnlyObservableCollections. I have a helper class that creates a projection from a source ObservableCollection to another Collection. Since ReadOnlyObservableCollection does not inherit from ObservableCollection and I only need operations in IList and INotifyCollectionChanged I was hoping to store my source collection as a combination of these two interfaces rather than requiring an ObservableCollection.

Community
  • 1
  • 1
Bryan Anderson
  • 15,969
  • 8
  • 68
  • 83
  • 2
    Short answer: no. Not without defining a third interface that inherits from IFirstInterface and ISecondInterface. – Anthony May 03 '10 at 03:22
  • 2
    My only thought is that you could have the same instance as two interface variables? In what circumstance did you need this? Could you provide some insight of what you were doing where you needed something like this? – Nate Zaugg May 03 '10 at 03:24
  • 1
    So I don't get the aversion to creating a simple class to handle this. – jcolebrand May 03 '10 at 03:30
  • 2
    @drachenstern The classes already exist. Let's say the two interfaces are IList and INotifyCollectionChanged. The user could supply an ObservableCollection, ReadOnlyObservableCollection, CompositeCollection, FreezableCollection, or ObservableDictionary. With the exception of the ObservableDictionary these are all built in to .Net. I've also had a lot of instances where I've wanted this where one of the interfaces is ISerializable. – Bryan Anderson May 03 '10 at 04:14
  • @Bryan Anderson - Yeah, but if it's a proper class then it gets both of them and you don't have to do funky semantics or casts, right? I guess if it keeps the code simpler, it'll work, but I just see it as a bit harder to read. YMMV. – jcolebrand May 03 '10 at 14:24

4 Answers4

20

If you want to constrain your method SetFoo to take only parameters that implement these two interfaces, then you are in luck:

public void SetFoo<T>(T value) where T : IFirstInterface, ISecondInterface
{
    _foo = value;
}

From this point on, any time you want to access your _foo member as one of either of these two interfaces, you'll just have to access it via casts: (IFirstInterface)_foo or (ISecondInterface)_foo, respectively.

You did say you'd like to avoid resorting to casts for compile-time safety; but I think, if you figure out a way to ensure that _foo gets initialized using SetFoo above, you can cast all you want with peace of mind.


I just realized the below describes something you specifically stated in the question you didn't want to do. So, I say, go with the above.

Another idea would be, since it looks like this _foo object is a class member (I'm basing this assumption on the _ in the variable name), you could define your class in this way:

class YourClassThatHasAFoo<T> where T : IFirstInterface, ISecondInterface {
    private T _foo;

    public void SetFoo(T value) {
        _foo = value;
    }
}

Whether this actually makes sense depends, obviously, on your specific scenario. You'll definitely have to think it through, as classes with constraints like this sometimes lead to issues you might not have expected down the road (such as that SetFoo now must take a parameter of type T, not just any class that implements your two interfaces).

Dan Tao
  • 125,917
  • 54
  • 300
  • 447
  • 1
    Note that `(IFirstInterface)_foo` is fragile. If you remove `IFirstInterface` from your constraints for `T`, it becomes a runtime cast. But you can, e.g., do `IFirstInterface _fooFirst = _foo` or [use other tricks to ensure you get a compiletime/static cast](http://stackoverflow.com/q/3894378/429091). – binki Aug 05 '16 at 17:53
  • Are there any updates as of 2022? – Stepan Zakharov Oct 27 '22 at 19:22
6

No, there is no way to declaratively ensure that a particular instance implements more than one interface.

One option MIGHT be possible using generics, though this would really only work for a function rather than a property.

public void Foo<T>(T arg)
    where T : IFirstInterface
    where T : ISecondInterface
{
    ...
}

Using type inference, you should be able to call it like this:

ConcreteType bar = new ConcreteType(); // this implements both

Foo(bar);
Adam Robinson
  • 182,639
  • 35
  • 285
  • 343
3

It is possible to define interfaces so that arbitrary combinations of them may be required and used in type-safe fashion. The key is to define an interface ISelf(Of Out T), whose one member, Self, is a property by which the object returns itself as a T, and then for each interface IFoo, declare a corresponding generic of the form IFoo(Of Out T), which inherits from both IFoo and ISelf(Of T). A class Wowzo which implements ISelf(Of Wowzo), IFoo(Of Wowzo), IBar(Of Wowzo), and IBoz(Of Wowzo), will implemenet IFoo(Of IBar), IBar(Of IFoo), IFoo(Of IBoz(Of IBar)), IFoo(Of IBar(Of IFoo(Of IBar(Of IBoz(Of IBar))))), etc. and may if necessary be typecast to any such type. If Thing is an IFoo(Of IBar(Of IBoz)), one can use it directly as an IFoo, or use Thing.Self as an IBar, or use Thing.Self.Self as an IBoz.

Example of how to compose three interfaces together this way with C#:

public interface ISelf<out T>
{
    T Self { get; }
}
interface IA { }
interface IA<T> : IA, ISelf<T> { }
interface IB { }
interface IB<T> : IB, ISelf<T> { }
interface IC { }
interface IC<T> : IC, ISelf<T> { }
class ConcreteThing
    : IA<ConcreteThing>
    , IB<ConcreteThing>
    , IC<ConcreteThing>
{
    public ConcreteThing Self => this;
}
public class ReferencingObject
{
    IA<IB<IC>> Thing { get; }

    void Method()
    {
        IA a = Thing;
        IB b = Thing.Self;
        IC c = Thing.Self.Self;
    }
}
binki
  • 7,754
  • 5
  • 64
  • 110
supercat
  • 77,689
  • 9
  • 166
  • 211
2

A variable in .NET has a type, and types can implement multiple interfaces. Something like this:

public interface Interface1 { }
public interface Interface2 { }
public class SupportsMuliple : Interface1, Interface2 { }

But from your question it seems like you want to have a variable implement multiple interfaces without having a type that implements those interfaces. This isn't really possible, but you could generate a type on the fly that implements the interfaces and hide the fact that there is a real type doing the magic. The mocking library moq does this using Castle DynamicProxy.

Lanting
  • 3,060
  • 12
  • 28
RationalGeek
  • 9,425
  • 11
  • 62
  • 90
  • Thanks for response. The types that implement the interfaces already exist, I just need a way to store and use them in an implementation agnostic way. – Bryan Anderson May 03 '10 at 05:00