I'm trying to make a generic class that takes 3 types, either a simple string, IList&开发者_StackOverflow中文版lt;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>
?
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.
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.
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...
}
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
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.
精彩评论