29

I have an object that implements two interfaces... The interfaces are:

public interface IObject
{
    string Name { get; }
    string Class { get; }
    IEnumerable<IObjectProperty> Properties { get; }
}
public interface ITreeNode<T>
{
    T Parent { get; }
    IEnumerable<T> Children { get; }
}

such that

public class ObjectNode : IObject, ITreeNode<IObject>
{
    public string Class { get; private set; }
    public string Name { get; private set; }
    public IEnumerable<IObjectProperty> Properties { get; set; }
    public IEnumerable<IObject> Children { get; private set; }
    public IObject Parent { get; private set; }
}

Now i have a function which needs one of its parameters to implement both of these interfaces. How would i go about specifying that in C#?

An example would be

public TypedObject(ITreeNode<IObject> baseObject, IEnumerable<IType> types, ITreeNode<IObject>, IObject parent)
{
    //Construct here
}

Or is the problem that my design is wrong and i should be implementing both those interfaces on one interface somehow

silkfire
  • 24,585
  • 15
  • 82
  • 105
TerrorAustralis
  • 2,833
  • 6
  • 32
  • 46
  • 1
    "Now i have a function which needs one of its parameters to implement both of these interfaces." Functions or parameters don't implement interfaces, classes implement interfaces. What do you mean? – McKay Nov 01 '10 at 22:01
  • see edits. I know that only classes can implement interfaces – TerrorAustralis Nov 01 '10 at 22:04
  • possible duplicate of [Is it possible to make a parameter implement two interfaces?](http://stackoverflow.com/questions/772053/is-it-possible-to-make-a-parameter-implement-two-interfaces) – Robert MacLean Nov 18 '14 at 11:39

4 Answers4

51
public void Foo<T>(T myParam)
    where T : IObject, ITreeNode<IObject>
{
    // whatever
}
Tara McGrew
  • 1,987
  • 19
  • 28
  • This is a good answer. I realised that i left some crucial piece of information out. The function i am refering to is the constructor for another class (The scenario is a Node building another node) Can generics be used in a constructor – TerrorAustralis Nov 01 '10 at 22:09
  • 2
    Since this answer is valid for my question i will accept it, but the constructor thing is causing me a headache :) – TerrorAustralis Nov 01 '10 at 22:49
  • In that case I think you'd have to make the class generic. It doesn't look like you can have a generic constructor on a non-generic class. – Tara McGrew Nov 02 '10 at 00:36
  • Good solution for methods. Unfortunately it's difficult to apply this solution to properties without making the all class generic. – AgostinoX Mar 25 '20 at 09:39
  • 1
    @AgostinoX Indeed. The value of a property has to have a single type. You could pick one interface as the property type, and have the setter verify that the value implements the other interface too, but there's no way for the getter to say that it will always return a value implementing both interfaces. (That's the kind of thing Code Contracts were good for.) – Tara McGrew Mar 27 '20 at 02:54
  • For Moq purposes I still had to create a shared interface in my test class which I could mock that inherited both interfaces, but this solution is great for the production code and kept that pure and clean. – Syntax Dec 09 '22 at 02:21
  • Here is a workaround for generic constructor [Generic Type in constructor](https://stackoverflow.com/questions/700966/generic-type-in-constructor). Not especially good, but better, than nothing. ;) – Rekshino Jun 29 '23 at 15:19
13

In C#, interfaces can themselves inherit from one or more other interfaces. So one solution would be to define an interface, say IObjectTreeNode<T> that derives from both IObject and ITreeNode<T>.

Anders Fjeldstad
  • 10,724
  • 2
  • 33
  • 50
  • 9
    -1: This would change the requirement. This method does not require the parameter to implement IObject and ITreeNode, it would require the parameter to implement IObjectTreeNode. So objects implementing both interfaces but not the combined are not allowed, while they should. – Stijn Van Antwerpen Dec 09 '16 at 10:14
3

It's probably easiest to define an interface that implements both IObject and ITreeNode.

public interface IObjectNode<T> : IObject, ITreeNode<T>
{
}

Another option, in case you don't expect the above interface would be used often, is to make the method/function in question generic.

public void Foo<T>(T objectNode) where T : IObject, ITreeNode<IObject>
C. Dragon 76
  • 9,882
  • 9
  • 34
  • 41
  • 5
    -1; this merely repeats earlier answers and doesn't acknowledge [the drawback pointed out by Stijn in the comments](http://stackoverflow.com/questions/4073440/specifying-multiple-interfaces-for-a-parameter#comment69322597_4073481) about the first approach. – Mark Amery May 16 '17 at 09:58
-5
public  void MethodName<TParam1, TParam2>(TParam1 param1, TParam2 param2) 
    where TParam1 : IObject
    where TParam2 : ITreeNode<IObject> 
anivas
  • 6,437
  • 6
  • 37
  • 45
  • 7
    You've defined one parameter that implements `IObject` and another that implements `ITreeNode`, but I think the asker needs a single parameter that implements both. – Tara McGrew Nov 01 '10 at 22:07