|
I see a lot of syntax here that does not make sense in C#, is this really a C# question?
Anyway, in C#, you can not use typeof(something) as type argument to something generic. Why don't you want to make Parent generic? This seems to be one of the many "I want to do something but I don't want to use the solution"-questions.. If you make Parent<T> generic, often you won't even need to make the type argument explicit, because one of the arguments of the ctor is of type T (at least that's how I read your post).
|
|
|
|
|
Yeah, forgive me, it was psuedocode.
Basically, the answer is that Parent is not generic. Parent objects don't logically come in different flavors, and there is no reason beyond this problem that I would need to make Parent generic. It would also be an implementation nightmare at this stage, and would require making Grandparent and all the other classes that reference Parent objects generic as well.
|
|
|
|
|
Where does that generics-explosion come from? The type must be known somewhere..
Edit: also, a bit more context would probably help.
|
|
|
|
|
This is a base dll; different implementations will need to use the Child objects differently. Only the implementation will know the type. The Grandparent and all the other classes that ref parent objects have no reason to know the type; only Child and Parent's dictionary of Child need to know.
So there's no way to use a type object as a generic param?
The constructor for Parent is really the only appropriate place to do this. I'm not sure what context you're looking for, but I'm happy to provide answers...
|
|
|
|
|
Pete Burkindine wrote: So there's no way to use a type object as a generic param?
There is one way.. through reflection. I really wouldn't recommend that.
Is there a specific reason to avoid making Parent generic? Such as static fields that must be shared across all instances of parent, not just the ones with the same generic type..
This is what you want, right? Except in a way that actually works.
class Parent
{
Dictionary<string, Child<T>> _d;
public Parent(Type T)
{
_d = new Dictionary<string, Child<T>>();
}
}
It's really not much different from this:
class Parent<T>
{
Dictionary<string, Child<T>> _d;
public Parent()
{
_d = new Dictionary<string, Child<T>>();
}
}
ps: syntax colouring appears to be broken.
|
|
|
|
|
I am open to trying the reflection method, if you could possible provide an example...
The problem with making parent generic is that then all the other classes that ref parent objects in the library will need to know what type it is, which means making them all generic as well. Essentially, the entire library would have to be generic just so one class can be. Coding with the library would be a nightmare, since most of the other classes have nothing to do with child objects and there is no logical relationship between them.
It would be like having to instantiate CashRegister(of Cat) objects because your pet store program has a PetList type that needs the type param. The cash register doesn't need to know that; it should be able to work with the, say, count and price fields on the petlist object without needing to know the cat's hair color. If that makes sense.
|
|
|
|
|
What if you give the Child<t> some interface to implement and make a dictionary of that instead? Or Object even. "the rest" can not use Child<t> anyway since it doesn't know T.
Pete Burkindine wrote: I am open to trying the reflection method, if you could possible provide an example...
Bad idea. Avoid reflection at (nearly) all costs.
warning: it's getting really late here, by now I'm probably not making any sense anymore
edit: 3565555 GET!
|
|
|
|
|
The idea behind making it generic was to avoid un/boxing and type conversions, so I don't want to use object (but am). The interface idea is very interesting; I will give that a try.
Can I ask why you are saying to avoid reflection? I've heard that but don't know why that is.
|
|
|
|
|
Pete Burkindine wrote: avoid reflection
Because it tends to be very slow. However, in cases like yours you can do it once and store (cache) the information so repeated accesses are quicker.
On the other hand, generics offer a whole lot more with a lot less trouble.
I'd still want to know why you don't want to go generic.
|
|
|
|
|
Check out some of the other messages in this thread... Basically it involves making the entire library generic just so one class can be... and having to specify the type parameter of that one class to all kinds of objects that have no logical relationship to it.
Parent objects have relationships to many other classes, so making Parent generic means all those classes have to be generic as well. And it makes no sense to describe, for instance, a Rocket<hamster> just because the astronaut's wife has a pet hamster.
|
|
|
|
|
Yes, I saw that, but it's not very convincing.
|
|
|
|
|
Are you saying that there is a way to avoid having to pass that type parameter to all the other classes that would then reference the generic parent objects?
For instance, there would be Granparent<t>, since Grandparent keeps a dictionary of Parent. And grandparent should be potentially allowed to have Parent<t> objects with different params for T. T is specific to the Child and has nothing to do with Grandparent or its relationship to the Parent objects.
And this becomes even less clear as you get farther away from the family tree. There is a whole other set of classes that keep an association to a particular Parent object, but do not in any way need to know T.
|
|
|
|
|
It still sounds like an exam on OO instead of something real, all these relations and grandparents and family trees..
|
|
|
|
|
I suppose it does. I am bound by my NDA and do not publish actual code. I promise it's a real situation
|
|
|
|
|
Pete Burkindine wrote: only Child and Parent's dictionary of Child need to know
That sounds fishy to me.
|
|
|
|
|
Could you be more specific?
|
|
|
|
|
No, not really.
But OK, so you have a class that contains a Dictionary of some type, but you don't want to specify that type in the usual way.
You tried passing in the type, but that didn't work. You could pass in a delegate to the constructor to use, but internally store objects.
What does the class do with the items in the Dictionary?
If another class passes the items back out, you could make that method generic.
sometype x = manager.GetItem<sometype> ( itemname ) ;
It still requires casting, and could involve boxing/unboxing, but only if you use value types.
I think I may have done something similar a while back, I'll have to take a look at what I did.
|
|
|
|
|
The parent class doesn't do anything with them. Consumers of the Parent access the dictionary through a property.
I think the delegate method and the generic method method ( ) both still use a dictionary<string,object> in the parent... avoiding that was the reason I wanted to make the child generic in the first place...
|
|
|
|
|
Pete Burkindine wrote: Consumers of the Parent access the dictionary through a property
Right, so they need to know the type. What do they do with the items?
P.S. How does your system of classes know what these consumers want?
modified on Sunday, August 15, 2010 12:42 AM
|
|
|
|
|
Right, and the consumers WILL know the type. They will be using the library, so they'll know what to put. I just don't want that type param to propagate to ever other class in the library! The only time you should need it is when you access the dictionary.
The consumers do standard things - do key comparisons, alter the value object, iterate the dictionary.values.
|
|
|
|
|
The consumers shouldn't be doing those things, only the manager class should be. Or is this a manager of Dictionaries?
|
|
|
|
|
No, there's just one dictionary. So you would normally wrap any dictionary in your own methods?
|
|
|
|
|
Probably.
I think you mentioned having your class instantiate items for its dictionary. Wouldn't your client classes simply pass items in?
Anyway, consider this:
public class ItemStore
{
private readonly System.Collections.Generic.Dictionary<string,object> dic =
new System.Collections.Generic.Dictionary<string,object>
(
System.StringComparer.CurrentCultureIgnoreCase
) ;
public void
Add
(
string Key
,
object Item
)
{
dic.Add ( Key , Item ) ;
return ;
}
public T
GetItem<T>
(
string Key
)
{
return ( (T) dic [ Key ] ) ;
}
public bool
Remove
(
string Key
)
{
return ( dic.Remove ( Key ) ) ;
}
}
ItemStore s = new ItemStore() ;
s.Add ( "name" , "James Bond" ) ;
s.Add ( "number" , 007 ) ;
System.Console.WriteLine ( s.GetItem<string> ( "NAME" ) ) ;
System.Console.WriteLine ( s.GetItem<int> ( "NUMBER" ) ) ;
P.S. I forgot to add locking. And you can make the class static if that suits your needs.
|
|
|
|
|
This would work, but since it still involves casting from object, it won't solve my problem. All access to the child objects happens through the Parent's dictionary and is short-lived (usually through iterators), so there is no performance benefit unless the dictionary itself is somehow made generic...
|
|
|
|
|
Pete Burkindine wrote: involves casting from object
Yes, of course, but it's hidden, and remember that it isn't a conversion, so it's very quick.
Pete Burkindine wrote: usually through iterators
I don't recall you mentioning that before. Please elaborate.
Pete Burkindine wrote: unless the dictionary itself is somehow made generic
Which we've been saying from the start.
|
|
|
|