• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 356
  • Last Modified:

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??


0
racineconde
Asked:
racineconde
  • 4
  • 3
  • 2
  • +1
1 Solution
 
wdosanjosCommented:
I think generics won't help you here, because you are changing the type returned by public MyCollection<T> MyCol {get;set;} at run-time.

If TypeA, TypeB, and TypeC are similar classes with the same methods / properties, you could create an interface (for example, MyInterface) and have TypeA, TypeB, and TypeC implement it.  Then you could have public MyCollection<MyInterface> MyCol {get;set;}.  Otherwise, the only thing you can return is probably MyCollection<object>.
0
 
rd707Commented:
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).
0
 
racinecondeAuthor Commented:
classA, classB and classC are completely different, but thanks for your input anyway.
0
Free recovery tool for Microsoft Active Directory

Veeam Explorer for Microsoft Active Directory provides fast and reliable object-level recovery for Active Directory from a single-pass, agentless backup or storage snapshot — without the need to restore an entire virtual machine or use third-party tools.

 
rd707Commented:
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 *

0
 
racinecondeAuthor Commented:
Is there then another way to achieve this without using generics?
0
 
rd707Commented:
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.
0
 
dimajCommented:
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.
0
 
rd707Commented:
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...
0
 
wdosanjosCommented:
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

0
 
racinecondeAuthor Commented:
Take a guess!
0

Featured Post

NFR key for Veeam Backup for Microsoft Office 365

Veeam is happy to provide a free NFR license (for 1 year, up to 10 users). This license allows for the non‑production use of Veeam Backup for Microsoft Office 365 in your home lab without any feature limitations.

  • 4
  • 3
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now