Solved

Generics in C#

Posted on 2011-03-07
10
333 Views
Last Modified: 2013-12-17
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
Comment
Question by:racineconde
  • 4
  • 3
  • 2
  • +1
10 Comments
 
LVL 23

Accepted Solution

by:
wdosanjos earned 500 total points
ID: 35061890
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
 
LVL 4

Expert Comment

by:rd707
ID: 35061975
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
 

Author Comment

by:racineconde
ID: 35062070
classA, classB and classC are completely different, but thanks for your input anyway.
0
 
LVL 4

Expert Comment

by:rd707
ID: 35062151
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
 

Author Comment

by:racineconde
ID: 35067888
Is there then another way to achieve this without using generics?
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 4

Expert Comment

by:rd707
ID: 35068641
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
 
LVL 7

Expert Comment

by:dimaj
ID: 35069858
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
 
LVL 4

Expert Comment

by:rd707
ID: 35070531
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
 
LVL 23

Expert Comment

by:wdosanjos
ID: 35070598
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
 

Author Closing Comment

by:racineconde
ID: 35231625
Take a guess!
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

In my previous article (http://www.experts-exchange.com/Programming/Languages/.NET/.NET_Framework_3.x/A_4362-Serialization-in-NET-1.html) we saw the basics of serialization and how types/objects can be serialized to Binary format. In this blog we wi…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now