-1

I have an application where i have say 10 objects of different types. I wish to have them in same list and iterate through them on many occasions. I cant push them into one list because they are of different types. So i created an interface and created a property that all objects share. Now i have the list of objects and type of the list is the "interface". When i iterate through the object, i can't access the specific properties of the object because the compiler will only know at runtime what object it is. So if i try to code Object_A.Name, visual studio will show error because it doesn't know they type of object. I can obviously do an if else or something similar to find the type of object and cast it, but i want to know of there is a better way, or if this whole approach of having an interface is wrong and if i should have begun in a different direction.

In the code below, i want to get the Devname, which i can't because its not part of the interface, but belongs to every object. I could make it part of the interface, but every now and then i may need to get a specific property. hence wanting to know if there is a way to do it.

foreach (ICommonDeviceInterface device in Form1.deviceList)
{
if (device.DevName.Equals(partnername))
{
return device.Port[portNo].PortRef;
}
}
  • It sounds like you want [pattern matching](https://learn.microsoft.com/en-us/dotnet/csharp/pattern-matching). I can't find a good question the same as yours, hopefully someone else can. :D – ProgrammingLlama Aug 20 '19 at 01:23
  • Can you give a concrete example of what you're trying to do? How do you know which property you want to call? You could use reflection to try to access a property by name, but I wonder if there's a better design to whatever you're trying to do. – Rufus L Aug 20 '19 at 01:30
  • I have many objects and i need to process them all. They all have more or less same methods in them but the code inside the method may vary. So i need to call all objects and call certain methods. Some objects will have same methods, some may have more methods than others and some less. I am thinking of a future point of view, when i may needs to do a process on some of them objects only, but i want one list to hold all the objects. I am very new to c# but i am very actively digging into it any any direction will be appreciated. Thanks. – flipflop_10 Aug 20 '19 at 01:38

2 Answers2

0

One way you could do this is by using reflection to try to get the property value of a named property from an object, using a helper method like:

public static object GetPropValue(object src, string propName)
{
    return src?.GetType().GetProperty(propName)?.GetValue(src, null);
}

Credit for above code goes to: Get property value from string using reflection in C#

This requires no checking types or casting, it just returns the value of the property, or null if it doesn't contain the property.

In use it might look like:

private static void Main()
{
    // Add three different types, which all implement the same interface, to our list
    var devices = new List<ICommonDeviceInterface>
    {
        new DeviceA {DevName = "CompanyA", Id = 1},
        new DeviceB {DevName = "CompanyB", Id = 2},
        new DeviceC {Id = 3},
    };

    var partnerName = "CompanyB";

    foreach (var device in devices)
    {
        // Try to get the "DevName" property for this object
        var devName = GetPropValue(device, "DevName");

        // See if the devName matches the partner name
        if (partnerName.Equals(devName))
        {
            Console.WriteLine($"Found a match with Id: {device.Id}");
        }
    }
}

Classes used for the sample above:

interface ICommonDeviceInterface
{
    int Id { get; set; }
}

class DeviceA : ICommonDeviceInterface
{
    public int Id { get; set; }
    public string DevName { get; set; }
}

class DeviceB : ICommonDeviceInterface
{
    public int Id { get; set; }
    public string DevName { get; set; }
}

class DeviceC : ICommonDeviceInterface
{
    public int Id { get; set; }
}
Rufus L
  • 36,127
  • 5
  • 30
  • 43
  • I have thought of reflections before. I read somewhere that its an expensive operation. And i honestly don't know how expensive, relatively. If i run this method on 150 objects in a loop, i am not sure if it has significant effect on performance. I mean, i am more like asking here, if it does? The solution looks good to me though. Thanks. – flipflop_10 Aug 20 '19 at 01:46
  • Good question. You'll have to try it and see, and compare to whatever other solutions you're trying. The good thing is that you don't have to add a new `else if` for every new type that gets added to the list. – Rufus L Aug 20 '19 at 01:50
-1

Use "as" and "is" to know what type of interface

public class A : ICommonDeviceInterface 
{
  public int AMember;
}
public class B :ICommonDeviceInterface 
{
  public int BMember;
}

foreach (ICommonDeviceInterface device in Form1.deviceList)
{

    if(device is A)
    {
       A a = device as A;
       a.AMember = 100;
    }
    else if(device is B)
    {
       B b = device as B;
       b.BMember = 123;
    }
}
TimChang
  • 2,249
  • 13
  • 25
  • *"I can obviously do an if else or something similar to find the type of object and cast it, but i want to know of there is a better way"* – Rufus L Aug 20 '19 at 01:31