Invalid Cast from UserControl to custom control - c#

I have several controls that all inherit from UserControl, and I have a MergeSort method that runs on UserControl types (to save me from writing out 6 different methods), but when I cast back to my custom controls after the sorting, it throws an error, what am I doing wrong? The mergesort method requires the Left property, which each custom control uses, so is there any other way I can do this?
MergeSort method looks like:
public UserControl[] MergeSort(UserControl[] array)
Cast looks like:
(CustomControl[])MergeSort(customControlArray);

I think you have to cast each of them manually:
CustomControl[] customControlArray;
...
UserControl[] sortedControls = MergeSort(customControlArray);
CustomControl[] sortedCustomControls = Array.ConvertAll<UserControl, CustomControl>(sortedControls, delegate(UserControl control)
{
return (CustomControl)control;
});
If you have .NET 3.5+ at your disposal you can use much "cooler" syntax. :)
Edit: the cooler syntax is:
UserControl[] sortedControls = customControlArray.ToList().ConvertAll(c => (CustomControl)c).ToArray();
:-)

(I deleted my previous answer because I think it was actually incorrect.)
It sounds like you need an abstraction between your controls and UserControl which represents common functionality. There are two main ways to accomplish this, and whichever one you use is a matter of personal coding preferences, how you plan to extend these further, how you organize your code in the project, etc...
Inherit from a base class. Basically, create a MyCustomControl (or whatever you want to name it) class which implements the common functionality between your custom controls. This would inherit from UserControl and your controls would inherit from this. Then your method would expect/return an array of this base class.
Implement an interface. You could create an ICustomControl (or whatever you want to name it) interface which represents the common functionality between your custom controls. Then your controls would inherit from UserControl as well as implement ICustomControl. Then your method would expect/return an array of this interface type.
I personally prefer the interface approach. Inheritance tends to be overused in a lot of people's object oriented code, and really shouldn't be. An interface better represents an abstraction (or code contract) as a type (as opposed to a class). But that's a much bigger discussion debate for another time, I suppose :)

Related

Is this an abuse of generics?

I sometimes find myself in a situation, where I want to express a type, which is a subtype of an inbuild class (e.g. a Wiforms control) and also implements a custom interface. I have several such classes that otherwise have no relation to each other. I use generics in these cases. Here is a simplified example:
interface IDescription
{
string GetDescription();
}
...
private string getDescription<T>(T control) where T : System.Windows.Forms.Control, IDescription
{
return control.Name + control.GetDescription();
}
However this seems like a little unconventional use of generics, because generics are usually used to write type agnostic code (like generic containers). In this code on the other hand generics are used solely because the lack of sufficient type expression.
My question is: Is this an abuse of generics? Are there any better way to write such code?
UPDATE 1
As Frank Hileman pointed out in this example adding the Name property to the interface would make this a non-issue. Let me add an other example:
private string getDescription<T>(T control) where T : System.Windows.Forms.Control, IDescription
{
return getData(control) + control.GetDescription();
}
private string getData(System.Windows.Forms.Control control)
{
...
}
UPDATE 2
Please note that adding a base class is sometimes not possible. For example:
There maybe a custom class subclassing TreeNode and an other one subclassing DataGridView.
No, it is not. The fact that generics are used to create generic containers, etc. does not mean that's the only use case of generics.
In this case, since your method does the same thing for different types that implements a common interface, it's completely fine and is not an abuse.
While it is not a better way, another way to write the getDescription method is to write a non-generic method taking either a Control or IDescription as input, and performing a dynamic cast to obtain a view on the instance as a different data type. However, now any type errors will occur at run-time instead of at compile time. If you are sure that all IDescription are also controls, it would work.
Another option is to put a Name property in IDescription, and use IDescription only.

Declare an interface as being implemented by a class

I created a class called MostRecentStack<T> which is a stack that only keeps a certain number of items, dropping the ones at the bottom to make room for new ones. I'd like to have a variable that can store a reference to either a regular ("infinite") stack, or one of my custom type, depending on the circumstances, but C# defines no generic "stack" interface. Normally this wouldn't be a problem, but I'd like System.Collections.Generic.Stack<T> to implement the interface as well.
As long as a class provides the required members, is there any way to, in the interface definition, tell the compiler to consider a class as implementing the interface? I'd like to be able to do this without having to use as or other methods of typecasting.
The exact thing you're asking for isn't possible. However, something like should be very similar to what you want:
public class CompatibleStack<T> : System.Collections.Generic.Stack<T>, IYourStackInterface<T>
{
}
The CompatibleStack is functionally equivalent to System.Collections.Generic.Stack, except it now implements IYourStackInterface.
As long as System.Collections.Generic.Stack has all the right members to implement IYourStackInterface, this should compile fine. And you can pass a CompatibleStack around as an IYourStackInterface without any problems.
No, it is not possible to add new interface to existing class that you don't own. Options:
if you get instance of the class via some dependency injection controller you may be able to wrap class with proxy that will implement interface by calling matching methods.
you can simply derive from existing class and add interface (if it is not sealed) and start using your class.
in your particular case as Baldrick pointed out you can do reverse - derive from existing class and implement interface.
you can try to use dynamic to get some duck typing (as both classes will have matching methods) for some performance, readability and strong type cost.
Side note: in general C# does not support duck typing, but there is one case (foreach) where implementing interface is not strictly required - just having correct methods on collection is enough to support foreach.

Change multiple inheritance into deriving from a template

Say I have a bunch of code for all controls, yet I need subclasses that interact with my software suite to use those common methods. I really want my subclass to derive from the control, not the class with the common code. (A MyEdit should derive from Edit, not from MyControl). Also, the suite interacts with controls using an interface which MyControl derives from. In order to do this in C++, I would use multi-inheritance like so
class MyEdit : public Edit, public MyControl;
class MyControl : public IControl;
However, I suddenly discover that I shouldn't use multi-inheritance if I want some controls to be C# which doesn't support multi-inhertiance.
So I thought I could do this...
class MyEdit : public MyControl<Edit>;
template class MyControl<Type> : public IControl;
Convert the common control stuff into a template, and give it the type of control I want to derive from.
However I'm not sure this will work, because the template templatizes Edit, but it doesn't necessarily create one does it? When I create the template will I actually be able to create the Edit?
And secondly, if this is possible, is it possible in C#? What would it look like?
I can't say I quite followed your question, but in regards to:
However I'm not sure this will work,
because the template templatizes Edit,
but it doesn't necessarily create one
does it? When I create the template
will I actually be able to create the
Edit?
I would go for
template<class Controlled_t>
class MyControl : public Controlled_t, public IControl
{
//My Control inherits from its templated class
}
so that
MyControl<Edit> inherits Edit (which is created) and the interface
In C#, a class can only inherit from one other class, but it can implement multiple Interfaces, so if you want a class that can override behavior for more than one polymorphic type at runtime, you have to use Interfaces. The drawback of Interfaces is that they have no properties or base method implementations, so you may have to duplicate some of the methods in classes that implement the same Interface.
Another, C#-y way to get polymorphic runtime behavior is by attaching delegates. A lot of times I've found that what looks like a multiple-inheritance situation is better expressed as a multicast-delegate situation.

How to hide methods from base class?

I use Castle Active Record' ActiveRecordBase class as a base class for my db objects. That allows me to take advantage of the AR pattern goodies, like:
MyClass clas = new MyClass();
clas.Number = 5;
clas.Save();
The problem is, for some objects, I want to hide these methods. How can I do that? I don't use interfaces for these objects.
Edit1:
To make it more clear: I want to have 10 classes inheriting from the base one, but 3 of them shouldn't expose some of the methods from the base class. So for example for MyClassB, this:
MyClassB clasB = new MyClassB();
clasB.Number = 5;
clasB.Save();
shouldn't be possible - this object SHOULDN'T be able to Save().
Edit2:
I've read c# hide from dervied classes some properties of base class . I agree that this is bad approach, but bear in mind that I have to use ActiveRecordBase, which I cannot simply modify (at least if I want to stick with the original Castle Active Record sources).
You don't do this.
You restructure your design so that the 7 objects inherit from one object that provides the functionality they want, the other 3 inherit from one that doesn't provide this, and they all inherit from the main "core" object. Think of it like a tree. Instead of trying to hide leaves from view, you simple change the location of the branch. I'm not sure this analogy works, but lets pretend it does.
If you want to hide them, the probably do not belong in that base class. I suggest expanding the inheritance hierarchy to achieve this.

C# typed <T> usercontrol in design mode gives error

I've got a custom class, which derives from UserControl.
The code:
public partial class Gallery<T> : UserControl where T : class, IElement, new()
This classworks like it's supposed to work. But, when I try to enter design mode of the form which contains these Gallery classes, it gives me errors:
Could not find type 'PresentrBuilder.Forms.Gallery'.
Please make sure that the assembly
that contains this type is referenced.
If this type is a part of your
development project, make sure that
the project has been successfully
built.
The variable 'pictureGallery' is either undeclared or was never
assigned.
Note: (pictureGallery actually is a Gallery<PictureElement>).
How can solve this? This way, I can't work in design mode which makes creating my userinterface quite hard.
The designer hates (i.e. doesn't support) generic controls, and that isn't going to change any time soon, so don't do that. Instead, consider having a property (or similar) that accepts a Type, and do some work at runtime (reflection etc) - or: don't use the designer.
For example, if you have:
public Type ControlType {get;set;} // comparable to T in the original
You can use:
IElement el = (IElement) Activator.CreateInstance(ControlType);
This will give you everything you currently have (new, IElement, etc) - but it just can't do any validation at compile-time.
Sometimes the easiest thing to do in this case is to make an empty subclass that qualifies the generic parameter.
This is often done with the ObservableCollection:
public class SomeItemCollection : ObservableCollection<SomeItem>{
}
It is kind of irritating, but it may solve your problems.
Like the others have stated, the Visual Studio Designer has a lot of trouble handling generics in controls. I've run into this myself when trying to implement something like a generic 'property viewer' class.
The solution that worked for me was defining an intermediary class, like Egor said. If I understand your question correctly, for your situation, that should be something like this:
public class PictureElementGallery : Gallery<PictureElement>
Then use the PictureElementGallery on your form, instead of Gallery < PictureElement >.
The designer should have no trouble with that.
Instead of having a generic control, have the control interact with a generic class that is separate from the control itself. Then pass this class into the control.

Categories

Resources