Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A list of multiple data types?

Tags:

c#

list

class

People also ask

Can a list have multiple data types?

Answer. A list in Python CAN contain different types of data. Each item in the list is separated by a comma and the entire list is enclosed in square brackets [] . To add a new item to the list, just edit the list starting before the closing bracket.

Can we have list with different data types?

Lists are the most versatile of Python's compound data types. A list contains items separated by commas and enclosed within square brackets ([]). To some extent, lists are similar to arrays in C. One difference between them is that all the items belonging to a list can be of different data type.

Can list have different data types in C#?

It is a dynamic array. It provides random access to its elements. An ArrayList automatically expands as data is added. Unlike arrays, an ArrayList can hold data of multiple data types.

Can a list store different types?

Question: Is it possible to store n number of lists of various types in a single generic list? Answer: Yes, by creating a list of list objects.


The easiest way to do this is to declare an interface, and have both types implement it:

public interface IMachine { … }

public class MachineLine : IMachine
{
    public double X1;
    public double Y1;
    public double X2;
    public double Y2;
    public double Thickness;
}

public class MachineCircle : IMachine
{
    public double CenterX;
    public double CenterY;
    public double Radius;
}

Then you can do this:

List<IMachine> m = new List<IMachine>();

You've got some answers explaining how to do this with an empty interface:

interface IMachineSomething {}
…
var m = new List<IMachineSomething>();

This works fine if all you want to put objects into that list. But what if you wanted to actually fetch objects from the list? What could you actually do with them, and what would the above solution force you to do?

The following shows that you can do even better with a non-empty interface.

IMachineSomething is an empty interface. That is, if you actually want to do something with the objects in your list, all you're going to see of them is the empty contract defined by that interface. All the actual functionality resides with the concrete class types. So you'd first have to check their type and then perform a type-cast in order to access the public fields:

foreach (IMachineSomething sth in m)
{
    if (sth is MachineLine)
    {
        var machineLine = (MachineLine)sth;
        machineLine.DoThis();
    }
    else if (sth is MachineCircle)
    {
        var machineCircle = (MachineCircle)sth;
        machineCircle.DoThat();
    }
    else …
}

Since you're working with a object-oriented language, there is a much better solution: Polymorphism. That is, put common functionality (properties as well as methods) in the interface, so that you won't need to distinguish between the types when you go through your list:

interface IMachineSomething
{
    void DoSomething();
}

class MachineLine : IMachineSomething
{
    …
    public void DoSomething() { DoThis(); } // example for implicit implementation, or…
}

class MachineCircle : IMachineSomething
{
    …
    void IMachineSomething.DoSomething() { DoThat(); } // …explicit implementation
}

Which allows you to get rid of the if (sth is …) type checks and subsequent type-casts, and simplify your code to this:

foreach (IMachineSomething sth in m)
{
    sth.DoSomething();
}

The loop no longer needs to care how each element gets processed exactly. All it needs to know that it must "do something" with an element, and the element itself will know what that means.

See also:

  • Conditionals and polymorphism (presentation) discusses the same main idea as this answer does (replacing if type checks with polymorphism).
  • Martin Fowler: Role interface (article), which are interfaces designed towards a specific interaction.

You have 2 ways:

1- Use inheritance:

public class MachineShape{}

public class MachineLine :MachineShape
{
    public double X1;
    public double Y1;
    public double X2;
    public double Y2;
    public double Thickness;
}

public class MachineCircle : MachineShape
{
    public double CenterX;
    public double CenterY;
    public double Radius;
}

List<MachineShape> m = new List<MachineShape>();


2- Use interface:

public interface IMachineShape{}

public class MachineLine : IMachineShape
{
    public double X1;
    public double Y1;
    public double X2;
    public double Y2;
    public double Thickness;
}

public class MachineCircle : IMachineShape
{
    public double CenterX;
    public double CenterY;
    public double Radius;
}

List<IMachineShape> m = new List<IMachineShape>();

And I recommend inheritance in your case...


Just create your own interface

public interface IMySillyInterface {}

public class MachineLine : IMySillyInterface
{
    public double X1;
    public double Y1;
    public double X2;
    public double Y2;
    public double Thickness;
}

public class MachineCircle : IMySillyInterface
{
    public double CenterX;
    public double CenterY;
    public double Radius;
}

List<IMySillyInterface> list = new List<IMySillyInterface> 
                                {
                                    new MachineCircle(), 
                                    new MachineLine()
                                };

You could make the two classes implement the same interface, and make that interface the contained generic type of your List.