tags:

views:

57

answers:

5

I'm trying to make a generic class that takes 3 types, either a simple string, IList<string> or a IList<OntologyStore>.

public class OntologyStore
{
}

public sealed class jim<T> where T:new()
{
    string J;
    IList<string> X = null;
    IList<OntologyStore> X1 = null;

    public jim()
    {
        if (typeof(T) == typeof(String))
        {
            J = string.Empty;
        }
        if (typeof(T) == typeof(OntologyStore))
        {
            X1 = new List<OntologyStore>();
        }
        if (typeof(T)==typeof(IList))
        {
            X = new List<string>();
        }
    }
}

I can easily create, which you would expect to work,

jim<OntologyStore> x1=new jim<jim<OntologyStore>()

as you would expect, but when I put in

jim<string> x2=new jim<string>()

the compiler reports the string is non abtract type, which you would expect.

Is it possible to create a generic class, which can instantiate as a class which holds string, or a IList<string> or an IList<OntologyStore>?

+1  A: 

This is the very definition of the case where you should not be trying to create such a class, but have an interface (or an abstract base) and make three different concrete classes deriving from it.

Jon
A: 

You cannot do this directly with generics. Generic constraints must specify a single type that is a constraint for all implementations... In your case, there is no common base class for System.String, IList<String>, and IList<OntologyStore> which is a unique base class or interface to those types (since System.Object and IEnumerable are the only common base types, I believe...)

However, I would recommend rethinking your design to avoid generics, in this case.

One option to prevent duplicating functionality would be to make a base class, and have 3 factory methods which construct and return a subclass for the specific type in question:

public class Jim
{
    protected Jim() {}

    public Jim Create(string value)
    {
        return new StringJim(value);
    }

    private class StringJim : Jim
    {
        public StringJim(string value) { // ...
        }
    }
    // Do same for IList<string> and IList<OntologyStore>..

    // Add common methods here...
}
Reed Copsey
+1  A: 

I think your problem has to do with the fact that String class does not have the public parameterless constructor as required by the "new()" constraint.

mfeingold
A: 

Hi,

you have to set

public sealed class jim where T: class, new()

if you want use string also

see here for more information: http://msdn.microsoft.com/en-us/library/d5x73970.aspx

MUG4N
A: 

If you are writing a generic class and you are doing things based on the type of T, it is usually a sign that this is not a good situation for generics or you are not constructing the class correctly.

In this case it looks like this would be better suited for using an interface to give the classes a shared type. If they end up sharing some kind of implementation, then use a base class instead of an interface.

unholysampler