Quercus Posted February 3, 2004 Posted February 3, 2004 I am working on an inherited ComboBox control, and want to restrict the type of objects that can be added to the Items collection to just a specific type of Object that I have developed. My control has special display properties, and any old object with a ToString method won't cut it. But I can't seem to override the Items property of the ComboBox class, or the Item, Add, AddRange or Insert methods of the ComboBox.ObjectCollection class in order to enforce this restriction. Instead of inheriting the ComboBox control, I could create a new custom control with a ComboBox as its only display element. Then I would have complete control over how these collections are implemented because I wouldn't have to inherit from the base class. But then I would have to write code to either implement or pass through all of the usefull properties and methods that come for free in the ComboBox and ComboBox.ObjectCollection classes, and I would really rather not have to go there. Is there anyway to override a non-virtual property or method? Is there a work around so that I can restrict the type of objects that can be added to the ObjectCollection class? Can I hide the non-virtual methods with a new method of the same name? Thanks. Quote
Administrators PlausiblyDamp Posted February 3, 2004 Administrators Posted February 3, 2004 really not tested this at all but something like the following may be a starting point. Public Class test 'whatever End Class Public Class MyComboBoxCollection Inherits ComboBox.ObjectCollection Sub New(ByVal cb As MyCombobox) MyBase.New(cb) End Sub End Class Public Class MyComboBox Inherits ComboBox Private objects As MyComboBoxCollection Public Shadows ReadOnly Property Items() As MyComboBoxCollection Get Return objects End Get End Property End Class you should be able to shadow the MyComboBox collection's add / remove etc methods. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
Quercus Posted February 3, 2004 Author Posted February 3, 2004 C# hides using the new instead of Shadows. Here's what I've got now: public class ItemCollection : ComboBox.ObjectCollection { // Stuff // Overload ObjectCollection.Add, which is declared as: // public int Add(object item) public int Add(MyItem item) { return base.Add(item); } // more stuff } The compiler will accept this as an overloaded version of the base class' Add method. However, the base class' Add method is still available if someone wants to call it with any old object - which defeats the purpose of my new Add method. I could do the following: public class ItemCollection : ComboBox.ObjectCollection { // Stuff // Hide ObjectCollection.Add, which is declared as: // public int Add(object item) public new int Add(object item) { // Test type of object here and throw an exception // if object is not of type MyItem. If it is of type // MyItem, then proceed return base.Add(item); } // more stuff } But this somehow seems like a brute force approach. Also, it wouldn't catch the error on build, but would wait until run time to throw an exception. I'd like to think of a better way. Quote
Administrators PlausiblyDamp Posted February 3, 2004 Administrators Posted February 3, 2004 Sorry - didn't realise you were using C#, if you shadow (new in this case) a method then it effectively hides the base classes implementation. i.e. public class ItemCollection : ComboBox.ObjectCollection { // Stuff // Hide ObjectCollection.Add, which is declared as: // public int Add(object item) public new int Add(yourObject item) //try this { // Test type of object here and throw an exception // if object is not of type MyItem. If it is of type // MyItem, then proceed return base.Add(item); } // more stuff } Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
Quercus Posted February 4, 2004 Author Posted February 4, 2004 Thanks for your help on this. public new int Add(yourObject item) will generate compile warnings, although it will compile, because there is no existing method Add(yourObject item) to hide. The program will still run, but the Add method is overloaded. One being with object and one being with yourObject. This doesn't implement the restriction that I am looking for. Any other thoughts? Quote
Administrators PlausiblyDamp Posted February 4, 2004 Administrators Posted February 4, 2004 My bad - should have tested my code properly under C#. I hate it when they make C# and VB.Net behave differently but in subtle ways. In C# the new keyword doesn't hide the original method signature, however in VB.Net the Shadows keyword does completely hide the original method!!! Will have a look to see if there is anything else that could be done.... as a quickie have you considered // Overload ObjectCollection.Add, which is declared as: // public int Add(object item) public int Add(MyItem item) { return base.Add(item); } public new int Add(object item) { if (item.GetType() != typeof(MyItem)) throw new ArgumentException("Can only accept MyItem", "item"); return 0; } Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
Quercus Posted February 4, 2004 Author Posted February 4, 2004 Yeah, that's what I was suggesting above and its the approach I am currently taking. What I don't like about this approach is that an error won't show itself until run time, whereas implementing a restriction by type in the memthod definition only will raise any errors on build. I'm hoping to find a cleaner way. Thanks. Quote
Quercus Posted February 4, 2004 Author Posted February 4, 2004 Let me ask this of everyone... Is it possible to hide a non-virtual method of a base class without implementing a replacement? In other words, the base class has the method: public int Add(object item) {} I want to hide this implementation entirely and overload it with a different one: public int Add(MyItem item) {} But with the original one hidden and not replaced, the user will only see the second method which takes a MyItem. Is this possible in C#? How would I do this? Quote
Quercus Posted February 5, 2004 Author Posted February 5, 2004 Well, after some looking around and help with interfaces, it would appear that I am here: My original goal was to create a new MyObjectCollection inherited from ObjectCollection, where the primary difference would be that MyObjectCollection would be strongly typed and accept only objects of MyItem, instead of any object. I was hoping I could somehow nuke ObjectCollection's Add(object item) method and replace it with my own Add(MyItem item) method. However, this does not appear possible in C# (please, please, correct me if I'm wrong!) Therefore, it would seem I have three options: 1) Inherit from ObjectCollection, hide the original Add method with a new Add(object item) method where I test the type of object passed in and throw an exception if it is not a MyItem. 2) Create a new class with a private interanal ObjectCollection method, and manually expose its interface: public class MyObjectCollection { private ObjectCollection myOC; // constructors and stuff public int Add(MyItem item) { return myOC.Add(MyItem); } // expose other methods & properties } 3) Create my own typed collection, inherited from CollectionBase, and implement the ObjectCollection interface as required. I'm leaning towards option #2, or maybe 3. Thanks. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.