Avatar of racineconde
racineconde
 asked on

Generics in C#

I am coming accross a very interesting problem.
I have the following classes defined as follows:
public class classA
{
        public int Type {get;set;}

        public MyCollection<T> MyCol {get;set;}

        //other properties and methods
}

public class TypeA
{
//class definition
}

public class TypeB
{
//class definition
}

public class TypeC
{
//class definition
}

the problem is that I want MyCollection<T> to hold either TypeA, TypeB or TypeC depending on the value in classA.Type when instantiating classA.

I found a way to build a generic collection that can hold any of the three class but the problem is tyhat when I am defining MyCol property for classA I have to pick a specific class (classA, classB or classC)

Any idea??


.NET ProgrammingC#

Avatar of undefined
Last Comment
racineconde

8/22/2022 - Mon
ASKER CERTIFIED SOLUTION
wdosanjos

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
rd707

My understanding is that generics allow you to write code that will accept any type. You still have to define that type at some point otherwise how can the compiler know how to compile it?

If the object have similarities, you'd probably be better off defining this in an interface and implementing it in your child objects (as wdosanjos mentions above).
racineconde

ASKER
classA, classB and classC are completely different, but thanks for your input anyway.
rd707

You could still do it of course, at the expense of a meaningful object structure. Not really how generics are supposed to be used, but it could be done... * shudders *

Your help has saved me hundreds of hours of internet surfing.
fblack61
racineconde

ASKER
Is there then another way to achieve this without using generics?
rd707

You can still use generics but implement each instance as type object. In the generic code though, you'd need to write code to handle each type.

Again, this would be slightly contradictory as to how generics are supposed to work.
dimaj

Just use a collection of Object. When you need to access your items, do a test to see if current Object is an instance of TypeA TypeB or TypeC and cast it accordingly.

Also, you could have an empty base class (let's say MyTypes) and make each of your classes derive from MyTypes. Then, make your collection of type MyTypes.
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
rd707

I'd just question why you're trying to shoehorn all these types into using the same code when all you're going to have to do is to write casts to pick them out anyway.

Unless this is just an academic exercise...
wdosanjos

It depends on the intended use of these classes. Here is a possible approach (sample runs as a console app):

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Test
{
    public class ClassA
    {
        private int _type;
        public int Type
        {
            get { return _type; }

            set
            {
                _type = value;

                switch (_type)
                {
                    case 1: MyCol = new List<TypeA>(); break;
                    case 2: MyCol = new List<TypeB>(); break;
                    case 3: MyCol = new List<TypeC>(); break;
                    default: MyCol = null; break;
                }
            }
        }

        public IList MyCol { get; set; }

        public IList<TypeA> MyColA { get { return (MyCol as List<TypeA>); } }

        public IList<TypeB> MyColB { get { return (MyCol as List<TypeB>); } }

        public IList<TypeC> MyColC { get { return (MyCol as List<TypeC>); } }

        //other properties and methods
    }

    public class TypeA
    {
        //class definition
    }

    public class TypeB
    {
        //class definition
    }

    public class TypeC
    {
        //class definition
    }

    // Test class
    public class Program
    {
        public static void Main()
        {
            var a = new ClassA();

            a.Type = 1;// a.MyCol is now of List<TypeA>

            a.MyCol.Add(new TypeA());
            a.MyCol.Add(new TypeA());
            a.MyCol.Add(new TypeA());
            a.MyCol.Add(new TypeA());

            foreach (var n in a.MyCol)
            {
                Console.WriteLine(n);
            }

            Console.WriteLine(a.MyColA);
            Console.WriteLine(a.MyColB);    // return null, since a.MyCol is a List<TypeA>
            Console.WriteLine(a.MyColC);    // return null, since a.MyCol is a List<TypeA>

            try
            {
                a.MyCol.Add(new TypeB()); // this will throw an exception
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            a.Type = 2; // a.MyCol is now of List<TypeB>

            a.MyCol.Add(new TypeB()); // this will not throw an exception
            a.MyCol.Add(new TypeB());
            a.MyCol.Add(new TypeB());
            a.MyCol.Add(new TypeB());

            foreach (var n in a.MyCol)
            {
                Console.WriteLine(n);
            }

            Console.WriteLine(a.MyColA);    // return null, since a.MyCol is a List<TypeB>
            Console.WriteLine(a.MyColB);
            Console.WriteLine(a.MyColC);    // return null, since a.MyCol is a List<TypeB>

        }
    }
}

Open in new window

racineconde

ASKER
Take a guess!
This is the best money I have ever spent. I cannot not tell you how many times these folks have saved my bacon. I learn so much from the contributors.
rwheeler23