Is this an abuse of generics? - c#

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.

Related

Is it possible to constrain the constructors of classes implementing an interface?

Is it possible to set a constrain that all classes implementing an interface must have, for example, an empty constructor? Like the where T : new() constraint in generic ?
No - its not possible to place any such constraints on derived classes or implementors of a given interface.
Such constrains generally wouldn't be a particularly good idea / useful anyway, as generally when working with an interface you are normally working with instances of objects that implement that interface in which case the object has naturally already been created and such constraints are redundant. (The exception of course being generics, in which case you can use the new() constraint).
My guess is that you are attempting to create some sort of plugin system and wish to constrain implementations of your plugin interface to have some default constructor that you can use for instantiation... if this is the case then there are normally better alternatives that you can use, such as the MEF.
Can you elaborate more on why exactly you need this?
There are only four ways I can think of that you might be given a class at run-time which isn't known at compile-time. You might be given an instance of an object which implements an interface, and want to produce another one like it. That scenario would best be handled by having the interface include a NewSimilarInstance() method. You might have a method in some class which gets passed a generic type parameter which is constrained to your interface. In that scenario, the routine which accepts the generic parameter could have a new() constraint. Otherwise, you could be given a .net System.Type object or some other representation (such a string) for the type. In these latter two scenarios, no compile-time validation is going to be meaningful; doing anything with the types will require Reflection, and so you may as well use Reflection to see if they allow the creation of new instances.
No, there's nothing like that. It would be slightly odd, given that the normal use of interfaces is that the code using an interface shouldn't need to care about how it was instantiated - they shouldn't care about what the implementation class is, just that it implements the interface.
If you have some special use for this, I suggest you just write unit tests for it - if all the implementations will be in the same assembly, it should be pretty straightforward to do so, and will catch any errors at nearly the same time as compile-time...
I think you need to use a virtual class for that.
As Justin said not only you can't constrain constructor signatures using an interface but also it's not possible using an abstract class.
Maybe if you would explain why you need to place such a constrain we could find some other solutions for your problem
Inject a Factory into your generic class that can instantiate your interface, and drop the new() constraint.
Something like:
public interface IFactory<out T>
{
T CreateInstance();
}
public class GenericClass<T>
{
private readonly IFactory<T> _factory;
public GenericClass(IFactory<T> factory)
{
_factory = factory;
}
public DoSomething()
{
//...
T foo = _factory.CreateInstance();
//...
}
}

Implementing a generic interface

I have a generic interface:
public interface IUnauthorizedRequestRespondable<out T> where T:class
{
T GetResponseForUnauthorizedRequest();
}
(I'm not sure why Resharper recommended T is "out", but that's not the question).
In my scenario, the object returned by GetResponseForUnauthorizedRequest is always of the type that implements the interface.
So all the interface's implementations look like:
public class SignInReturnedObject : IUnauthorizedRequestRespondable<SignInReturnedObject>
(class name and the type in brackets are always the same).
Which seems a bit awkward - isn't there a neater way to tell the compiler that the interface's method returns the type it's a part of?
Thanks.
As far as I know, there is no way to do that currently in C#.
A theoretical side-note: The feature that would allow you to do this is called self types but that's not available in C#. The idea of the feature is that you have a special type that refers to the actual type of this, so if you had a special type named self, you could probably write something like:
public interface IUnauthorizedRequestRespondable {
self GetResponseForUnauthorizedRequest();
}
...and the actual type used in place of self when you have a class SignInReturnedObject implementing the interface would be SignInReturnedObject, but unfortunatelly, that's not
available in C# :-)
If the only way you want to use that template is in that manner, I would use:
public interface IUnauthorizedRequestRespondable<T> where T:IUnauthorizedRequestRespondable<T>
{
T GetResponseForUnauthorizedRequest();
}
This has the advantage of guaranteeing it isn't used in any other way.
The class declaration won't change, but I don't see anything as awkward in this myself. Considering that you are defining a relationship between the class and itself, any more concise form might be inadvisable.
Actually, that about sums it up. That is how the syntax works.
You can see it used in .NET itself with the IEquatable inteface--you are almost always comparing an object to itself, yet you always have to provide your own class name as a template parameter.
This is simply to provide flexibility such that you can compare to anything, not necessarily yourself.
You can create a nongeneric version and just use that but I think it is more trouble than it is worth
public interface ICastUnauthorizedRequestRespondable : IUnauthorizedRequestRespondable<SignInReturnedObject>
{
}
Since T can be any class (does not have to be the class you are implementing) you need to name your class.
public class SignInReturnedObject : IUnauthorizedRequestRespondable<ANYCLASS>

Force calling the derived class implementation within a generic function in C#?

Ok so I'm currently working with a set of classes that I don't have control over in some pretty generic functions using these objects. Instead of writing literally tens of functions that essentially do the same thing for each class I decided to use a generic function instead.
Now the classes I'm dealing with are a little weird in that the derived classes share many of the same properties but the base class that they are derived from doesn't. One such property example is .Parent which exists on a huge number of derived classes but not on the base class and it is this property that I need to use.
For ease of understanding I've created a small example as follows:
class StandardBaseClass {} // These are simulating the SMO objects
class StandardDerivedClass : StandardBaseClass {
public object Parent { get; set; }
}
static class Extensions
{
public static object GetParent(this StandardDerivedClass sdc) {
return sdc.Parent;
}
public static object GetParent(this StandardBaseClass sbc)
{
throw new NotImplementedException("StandardBaseClass does not contain a property Parent");
}
// This is the Generic function I'm trying to write and need the Parent property.
public static void DoSomething<T>(T foo) where T : StandardBaseClass
{
object Parent = ((T)foo).GetParent();
}
}
In the above example calling DoSomething() will throw the NotImplemented Exception in the base class's implementation of GetParent(), even though I'm forcing the cast to T which is a StandardDerivedClass.
This is contrary to other casting behaviour where by downcasting will force the use of the base class's implementation.
I see this behaviour as a bug. Has anyone else out there encountered this?
I see this behaviour as a bug.
This behavior is correct. Since your method DoSomething is constraining T to StandardBaseClass, you only have access to the specific methods of StandardBaseClass, not any methods or properties of a derived class. Since StandardBaseClass does not have a Parent property, this is invalid, and should be invalid, by design.
There are two potential options here - You can use reflection to pull out the Parent property, or use C# 4's dynamic type, and treat this as a dynamic object. Both bypass the standard type checking in the compiler, however, so will require you to do extra type checking at runtime to verify that the Parent property exists.
Create an interface that contains the Parent property. Have each class that has a Parent property implement that interace. You will then be able to create a generic method that accepts a parameter of type IHaveParent, and it will do the right thing.
For anyone that is interested an succinct answer to this situation is answered by Stephen Cleary on msdn here:
http://social.msdn.microsoft.com/Forums/en-AU/csharpgeneral/thread/95833bb3-fbe1-4ec9-8b04-3e05165e20f8?prof=required
To me this is a divergence in the class hierarchy. By this this I mean that either the base class has parent, or the derived classes with Parent are derived from an abstract child of the base.
Lol as John says, an interface as opposed to an abstract class is sufficient too.
You idea won't work because the compiler can never guarantee that the base class actually would have such a property. And it won't just select the "right" one based on if it has it or not.
The only way you can do this is using reflection and then test at runtime if the requested property exists on the inspected class. You have to judge yourself if that is a viable way to do for your project (reflection is slow and requires maximum rights).
This is correct, as the compiler only knows that it can bind to your type as a StandardBaseClass. The binding is not done at runtime (where it could potentially decide to use the StandardDerivedClass overload.
If you know that it's a StandardDerivedClass, then why not just cast it as such?
object Parent = ((StandardDerivedClass)foo).Parent;
It's a bit ugly, but you can accomplish this using a Registration system, where you register delegates for different possible derived classes that expose the 'shared' property/method and then use something like a Dictionary<Type,Func<SomeT>> to store the delegates. If you know all of the derived types ahead of time and don't have to load plug-ins or the like, you can also use the classic ugly if/else-if structure. Either way you're basically creating your own substitute for what should have been supported by the virtual method table.

C#: Specify that a function arg must inherit from one class, and implement an interface?

I'm making a game where each Actor is represented by a GameObjectController. Game Objects that can partake in combat implement ICombatant. How can I specify that arguments to a combat function must inherit from GameObjectController and implement ICombatant? Or does this indicate that my code is structured poorly?
public void ComputeAttackUpdate(ICombatant attacker, AttackType attackType, ICombatant victim)
In the above code, I want attacker and victim to inherit from GameObjectController and implement ICombatant. Is this syntactically possible?
I'd say it probably indicates you could restructure somehow, like, have a base Combatant class that attacker and victim inherit from, which inherits from GameObjectController and implements ICombatant.
however, you could do something like
ComputeAttackUpdate<T,U>(T attacker, AttackType attackType, U victim)
where T: ICombatant, GameObjectController
where U: ICombatant, GameObjectController
Although I probably wouldn't.
Presumably all ICombatants must also be GameObjectControllers? If so, you might want to make a new interface IGameObjectController and then declare:
interface IGameObjectController
{
// Interface here.
}
interface ICombatant : IGameObjectController
{
// Interface for combat stuff here.
}
class GameObjectController : IGameObjectController
{
// Implementation here.
}
class FooActor : GameObjectController, ICombatant
{
// Implementation for fighting here.
}
It is only syntactically possible if GameObjectController itself implements ICombatant; otherwise, I would say you have a design problem.
Interfaces are intended to define the operations available on some object; base classes identify what that object is. You can only pick one or the other. If accepting the ICombatant interface as an argument is not sufficient, it might indicate that ICombatant is defined too narrowly (i.e. doesn't support everything you need it to do).
I'd have to see the specifics of what you're trying to do with this object in order to go into much more depth.
What if you did this instead:
public class GameObjectControllerCombatant : GameObjectController, ICombatant
{
// ...
}
Then derive your combatant classes from this instead of directly from GameObjectController. It still feels to me like it's breaking encapsulation, and the awkwardness of the name is a strong indication that your combatant classes are violating the Single Responsibility Principle... but it would work.
Well, sort of. You can write a generic method:
public void ComputeAttackUpdate<T>(T attacker, AttackType type, T victim)
where T : GameObjectController, ICombatant
That means T has to satisfy both the constraints you need. It's pretty grim though - and if the attacker and victim could be different (somewhat unrelated) types, you'd have to make it generic in two type parameters instead.
However, I would personally try to go for a more natural solution. This isn't a situation I find myself in, certainly. If you need to regard an argument in two different ways, perhaps you actually want two different methods?
If you control all the classes in question, and if GameObjectController doesn't define any fields, the cleanest approach would be to define an IGameObjectController (whose properties and methods match those of GameObjectController) and an ICombatantGameObjectContoller (which derives from both IGameObjectController and ICombatant). Every class which is to be usable in situations that require both interfaces must be explicitly declared as implementing ICombatantGameObjectController, even though adding that declaration wouldn't require adding any extra code. If one does that, one can use parameters, fields, and variables of type ICombatantGameObjectController without difficulty.
If you can't set up your classes and interfaces as described above, the approach offered by Jon Skeet is a generally good one, but with a nasty caveat: to call a generic function like Mr. Skeet's ComputeAttackUpdate, the compiler has to be able to determine a single type which it knows is compatible with the type of the object being passed in and with all of the constraints. If there are descendants of GameObjectController which implement ICombatant but do not derive from a common base type which also implements GameObjectController, it may be difficult to store such objects in a field and later pass them to generic routines. There is a way, and if you need to I can explain it, but it's a bit tricky.

Using empty parent class just to group other classes. Is there a better approach?

I have several classes that conceptually belong to one tier. They have no common properties which is why they have no need to inherit from some base class.
I also have a few methods that deal with these classes. Some of them are templates of the following style:
public SomeClass
{
public void SomeMethod<T> (T argument) where T : BaseClass
{
/* Do something */
}
}
So I'm using this WHERE keyword just to secure the code (from myself I suppose), so that I don't by mistake feed to this method something else.
Naturally I made those other classes derive from BaseClass which is empty and has no other purpose (at least for now) than to group other classes.
This is probably not that good approach but anyway I'm using it.
Is there a better way to do this?
EDIT: After consideration I decided not to go with that approach and just removed that base class. Good enough without it. I cannot make the code absolutely perfect anyway, and the less unneeded thing there are the better.
Use a marker (empty) interface instead of a base class:
public void SomeMethod<T> (T argument) where T : ISomeInterface
+1 on Jeff's answer. Tagging ("marker") interfaces are common in both C# and Java frameworks. They let you assign a common type to "class A" so that another class ("class B") can be ignorant of class A's concrete type.
As with anything this flexible, it's easy to misuse, but in your case it definitely fills the bill.
Perhaps a more concrete example would provide a little more perspective. As it stands, I'd say you should not group classes in this way.
Your SomeMethod() method obviously does not reference any of the properties of the argument (or if it does, it also must be casting the argument to different type(s)); What is the reason for securing the code "from yourself"? What would happen if you were to call the method passing in an object that was not approved?
If the argument constraint is absolutely necessary, I would recommend as Grybyx did, use an Interface. That'll save you from issues with multiple inheritance.

Categories

Resources