|
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.
|
|
|
|
|
Oh, and maybe consider generic Extension Methods.
|
|
|
|
|
Gahh! I had assumed that I couldn't derive from Dictionary, but you can. So here's a better version of that.
public class ItemStore : System.Collections.Generic.Dictionary<string,object>
{
public ItemStore
(
)
: base()
{
return ;
}
public ItemStore
(
System.StringComparer StringComparer
)
: base
(
StringComparer
)
{
return ;
}
public T
GetItem<T>
(
string Key
)
{
return ( (T) this [ Key ] ) ;
}
}
(It may still need locking.)
|
|
|
|
|
The consumers work with the child objects by themselves; the library is setup with delegates passed in by the consumer. There are some "generic" (not in the programming sense, but just the "here ya go" basic implementation kind of a sense) methods that could be written as actual generics or just enforce Object as the type, but the average consumer assembly for this library will be much too complicated to make use of them.
|
|
|
|
|
I'm pretty sure you'll need to go generic, and the sooner the better.
|
|
|
|
|
Here are the proposed solutions, from here and another forum:
1. Have Child implement an interface, IChildItem, and make Parent's dictionary be <string, ichilditem=""> instead.
2. Wrap the dictionary in a set of generic methods in the Parent class
3. Generic Extension methods to the dictionary
modified on Sunday, August 15, 2010 2:56 PM
|
|
|
|
|
I am creating a user control which will work as a Telephone number validator.
I want that when Regex is not a match the Text property should not return any kind of string. Can someone help with the code, as with my code, the errorprovider is instantiated but it still continues and returns the invalid phone number
public override string Text
{
get {
string phone = textBox1.Text.Trim() + textBox2.Text.Trim() + textBox3.Text.Trim();
if (!Regex.IsMatch(phone, @"^\d{9}$"))
{
errorProvider1.SetError(textBox3, "Please provide a valid phone number");
errorProvider1.SetIconAlignment(textBox3, ErrorIconAlignment.MiddleRight);
}
return phone;
}
set {
string phone;
phone = value;
textBox1.Text = phone.Substring(0, 3);
textBox2.Text = phone.Substring(3, 3);
textBox3.Text = phone.Substring(6);
}
}
|
|
|
|