'Using abstract class property in interface in C# [duplicate]

I am trying to deal with a problem of with interfaces and implementations. See code below.

public interface IMachine
{
    string Name { get; set; }
    List<IElement> Elements { get; set; }
    List<IWire> Wires { get; set; }
}

public class ElementA : IElement {  }   

public class ElementB : IElement {  }   

public class WireA : IWire {  }   

public class WireB : IWire {  }  

public class MachineA : IMachine
{
    public List<ElementA> Elements { get; set; }
    public List<WireA> Wires { get; set; }
}

public class MachineB : IMachine
{
    public List<ElementB> Elements { get; set; }
    public List<WireB> Wires{ get; set; }
}

What I want to do in my program, is to iterate over IMachine elements stored in a list, and then access all Wire and Element members, without taking too much care about the exact type.

Is this even possible? I did some experiments with abstract classes, casting, but I'm stuck.

Well, of course code above will not compile as I get error, that I am missing implementation of interface member.

A/B classes vary in details (basic properties are same, but I use some specific ones for each class), so casting does not work, too.



Solution 1:[1]

Your fundamental problem is that a List<WireA> is not a List<IWire>, so you are not fulfilling the interface contract. If you want to access the lists as list of a specific type (rather than List<IElement>, for example) and avoid casting the elements, you could use generics:

public interface IMachine<TElement, TWire> where TElement : IElement, TWire : IWire
{
    string Name { get; set; }
    List<TElement> Elements { get; set; }
    List<TWire> Wires { get; set; }
}

public class MachineA : IMachine<ElementA, WireA>
{
    public List<ElementA> Elements { get; set; }
    public List<WireA> Wires { get; set; }
}

public class MachineB : IMachine<ElementB, WireB>
{
    public List<ElementB> Elements { get; set; }
    public List<WireB> Wires{ get; set; }
}

Solution 2:[2]

Suppose your IWire required the implementation of GetName() and there existed at least one IWire object in your Wires collection then the code would return whatever was implemented by the instance of IWire's GetName() method.

var machines = new List<IMachine>();
machines.Add(new MachineA());
machines.Add(new MachineB());
machines.Add(new MachineA());

foreach(var machine in machines)
{
    Console.WriteLine(machine.Wires[0].GetName());
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 D Stanley
Solution 2 Ross Bush