Yesterday, I was explaining C#'s generic constraints to my friends. When demonstrating the where T : CLASSNAME constraint, I whipped up something like this:
public class UnusableClass<T> where T : UnusableClass<T>
{
public static int method(T input){
return 0;
}
}
And was really surprised to see it compile. After a bit of thinking, however, I figured it was perfectly legal from the point of view of the compiler - UnusableClass<T> is as much of a class as any other that can be used in this constraint.
However, that leaves a couple of questions: how can this class ever be used? Is it possible to
Instantiate it?
Inherit from it?
Call its static method int method?
And, if yes, how?
If any of these is possible, what would the type of T be?
This approach is widely used in Trees and other Graph-like structures. Here you say to compiler, that T has API of UnusableClass. That said, you can implement TreeNode as follows:
public class TreeNode<T>
where T:TreeNode<T>
{
public T This { get { return this as T;} }
public T Parent { get; set; }
public List<T> Childrens { get; set; }
public virtual void AddChild(T child)
{
Childrens.Add(child);
child.Parent = This;
}
public virtual void SetParent(T parent)
{
parent.Childrens.Add(This);
Parent = parent;
}
}
And then use it like this:
public class BinaryTree:TreeNode<BinaryTree>
{
}
Well.
public class Implementation : UnusableClass<Implementation>
{
}
is perfectly valid, and as such makes
var unusable = new UnusableClass<Implementation>();
and
UnusableClass<Implementation>.method(new Implementation());
valid.
So, yes, it can be instantiated by supplying an inheriting type as the type parameter, and similarly with the call to the static method. It's for instance useful for tree-like structures where you want to generically specify the type of children the node has, while it being the same type itself.
If any of these is possible, what would the type of T be?
They are all possible, and you are the one who is gonna determine what is the type of T.For example let's assume there is a type that inherits from UnusableClass<T>
class Foo : UnusableClass<Foo> { }
Now you can instantiate UnusableClass<Foo> because Foo satisfies the constraint:
UnusableClass<Foo> f = new UnusableClass<Foo>();
Then the type of T become Foo and if you try to call method you need to pass an instance of Foo.
Related
I want to subclass a large number of classes so that they will all contain a certain set of the same properties. What would be the right way to do it in order to avoid repetition? I thought of using generics like:
public class SuperT<T> : T
{
//the same set of properties
}
But the compiler says
Cannot derive from 'T' because it is a type parameter
EDIT: I am trying to subclass some classes in a third party assembly so I cannot use a base class.
For example, the types are "Image", "Label", "Button" etc and I want to subclass them all to contain a property like "Radius". (So that I would use SuperImage element in XAML and when I set it's Radius property from XAML, I will be able to run some certain logic.)
One other way I just thought of right now is using T4 templates. I wonder if there is a way to do this with generics without resorting to templates? I cannot understand why the compiler rejects it.
If these classes all share a common base class or common interface you could write an extension method.
public static class ShapeExetnsionsExtLib
{
public static double Radius(this ShapeBase shape){
return /*calculate radious*/;
}
}
From comments
I am trying to subclass some classes in a third party assembly so I cannot use a base class.
For example, the the types are "Image", "Label", "Button" etc and I want to subclass them all to contain a property like "radius".
Yes they share common base classes but I cannot add anything new to them.
I don't think generics have anything to do with this, however inheritance is probably what you're looking for.
There are two types of inheritance that you can use to subclass, and extension methods work to "superclass"... sort of.
Is-A inheritance
Has-A inheritance
And to simply add a similar method to a bunch of third party objects, you'll use an extension method.
Is-A inheritance
Use a base class if you've got similar method implementations.
public abstract class BaseFoo {
public void Bar() {
// actual code
}
}
public class Foo : BaseFoo
{
}
var foo = new Foo();
foo.Bar();
Use an Interface if you need to implement the same method on each class.
public interface IFoo {
void Bar();
}
public class Foo : IFoo {
public override void Bar(){
// bar implementation
}
}
var foo = new Foo();
foo.Bar();
Combining the two is also allowed, but you can only inherit on base class, where you can inherit multiple interfaces.
Has-A inheritance
This is particularly useful with dependency injection, but it's simply the notion that you have an instance of another class to work with. It's essentially a wrapper class for you to work with.
public class Foo {
private readonly ThirdPartyFoo _tpFoo;
void Foo(ThirdPartyFoo tpFoo) {
_tpFoo = tpFoo;
}
public void Bar(){
// now I can do something with _tpFoo;
_tpFoo.Bar();
}
}
var tpFoo = new ThirdPartyFoo();
var foo = new Foo(tpFoo);
foo.Bar(); // invokes the underlying tpFoo
Lastly, if you just need to add a method to existing classes, then you create an extension method.
public static class ViewExtensions()
{
// this assumes your Image, Button, Label all inherit from View.
public static Whatever Radius(this View view) {
// do your radius work.
}
}
Just Use a base class:
public class Base
{
public int Id { get; set; }
public string Name { get; set; }
}
And inherite from it:
public class A : Base
{
}
public class B : Base
{
}
In general, you want to use one of the answers already posted about using a base class and inheriting from that. However, if the classes are in a third party library and are marked as sealed, then you will need to create a wrapper class to use as a base class.
(Note that this option is a workaround and doesn't truly inherit from the third party class, so things in that class that are marked as protected won't be accessible without a liberal use of reflection.)
// The sealed class within another library
public sealed ThirdPartyClass
{
public ThirdPartyClass(int i) { }
public int SomeProperty { get; set; }
public int SomeMethod(string val) { return 0; }
public static void SomeStaticMethod() { }
}
// The wrapper class to use as a pseudo base class for ThirdPartyClass
public class BaseClass
{
private ThirdPartyClass _obj;
public BaseClass(int i) { _obj = new ThirdPartyClass(i); }
public int SomeProperty
{
get { return _obj.SomeProperty; }
set { _obj.SomeProperty = value; }
}
public int SomeMethod(string val) { return _obj.SomeMethod(val); }
public static SomeStaticMethod() { ThirdPartyClass.SomeStaticMethod(); }
}
// The child class that inherits from the "base" BaseClass
public class ChildClass : BaseClass
{
}
First of all, this might be a logical problem. What if you are going to extend a sealed class? Or Int32 class? Delegate?
Anyway, the way I recommend is to create an interface and implement all the functions you need in the subclass.
I would like call:
Question<Entity> question =
Question<Entity>.Create(
Choice.Create().
AddFollowUpQuestion(Question.Create()).
AddFollowUpQuestion(Question.Create()),
Choice.Create()
);
But the best C# allows me to do is:
Question<Entity> question =
Question<Entity>.Create(
Choice<Entity>.Create().
AddFollowUpQuestion(Question<Entity>.Create()).
AddFollowUpQuestion(Question<Entity>.Create()),
Choice<Entity>.Create()
);
I am trying to clean some code up, basically just adding syntactic sugar so some definitions I have to make a lot of are easier to read.
Both intelisense and the compiler know they are expecting the parameter to be of type Choice because it is a method of the generic class. But it still requires me to type out the type of T for the passed argument.
A bit more abstract: I am trying to create a top level generic class in which all properties which are also generic types will be using the same type for T.
Can anyone help me solve this puzzle? Or at least explain me why I have to type the same Type over and over again?
Simplified class definitions:
public class Question<T> where T : Entity
{
public static Question<T> Create(params Choice<T>[] choices)
{
return new Question<T>
{
Choices = choices
};
}
private Choice<T>[] Choices { get; set; }
}
public class Choice<T> where T : Entity
{
public static Choice<T> Create()
{
return new Choice<T>();
}
public Choice<T> AddFollowUpQuestion(Question<T> followUpQuestion)
{
FollowUpQuestions.Add(followUpQuestion);
return this;
}
private static List<Question<T>> FollowUpQuestions { get; set; }
}
public abstract class Entity
{
}
C# can infer the method that you want to call based on the type of a parameter, but it cannot infer the type of the class on which to call a method that produces a parameter of the required type: the "type inference magic" goes only one way.
Essentially, you giving the compiler Choice.Create() expression and the fact that its result is being passed to a method expecting Choice<Entity>, and asking it to deduce that Choice is actually a generic type (despite the fact that there may be a non-generic Choice in the system), and it has a Create() method that returns Choice<T>. Although the compiler could possibly do it, implementation would be expensive, and could potentially be a breaking change.
However, you can make a generic helper method that would provide the same T to multiple classes, like this:
static Question<T> MakeQuestion<T>() {
return Question<T>.Create(Choice<T>.Create());
}
Now you can call
Question<Entity> question = MakeQuestion<Entity>();
and pass the type parameter only once.
Edit: As far as the more elaborate example from your edit is concerned, you should be able to shorten the API by introducing a factory that is generic on Entity, and lets you create questions, follow-ups, etc.
class QuestionFactory<T> {
public Question<T> CreateQuestion() {
...
}
public Choice<T> CreateChoice() {
...
}
}
Now you can do this:
var qf = new QuestionFactory<Entity>();
var question = qf.CreateQuestion(
qf.CreateChoice().
AddFollowUpQuestion(qf.CreateQuestion()).
AddFollowUpQuestion(qf.CreateQuestion()),
qf.CreateChoice()
);
A common thing to do is to create non-generic classes for the factory method:
public static class Question {
public static Question<T> Create<T>(Choice<T> choice) {
return Question<T>.Create(choice);
}
}
...
Question<Entity> question = Question.Create(Choice<Entity>.Create());
One way is to change Question.Create() to not expect a Choice to be provided, rather it creates the Choice itself. It makes the code a little simpler and you can achieve your goal.
public class Question<T> where T : Entity
{
public static Question<T> Create()
{
return new Question<T>
{
Choice = Choice<T>.Create()
};
}
private Choice<T> Choice { get; set; }
}
public class Choice<T> where T : Entity
{
public static Choice<T> Create()
{
return new Choice<T>();
}
}
public abstract class Entity
{
}
Depending on the context, this can be a positive change as the responsibility of creation of a Choice is moved to the Question, in other words you abstract the callers of Question.Create() from the hassle of creation of Choice.
On the other hand, it increases the coupling of Question and Choice.
Which one is prefered, depends on the rest of the architecture.
Of course, I assumed that T is really needed in Choice.
I've got an abstract class like this;
public abstract PropertyBase
{
public static System.Type GetMyType()
{
return !!!SOME MAGIC HERE!!!
}
}
I'd like to subclass it, and when I call the static GetMyType(), I'd like to return the subclass's type. So if I declare a subtype;
public class ConcreteProperty: PropertyBase {}
then when I call
var typeName = ConcreteProperty.GetMyType().Name;
I expect 'typeName' to be set to "ConcreteProperty." I suspect there's no way to do it, but I'm interested if anyone out there knows a way to get this info.
(The particular problem I'm trying to solve is the verbosity of dependency properties in WPF; I'd love to be able to do something like this;
class NamedObject : DependencyObject
{
// declare a name property as a type, not an instance.
private class NameProperty : PropertyBase<string, NamedObject> { }
// call static methods on the class to read the property
public string Name
{
get { return NameProperty.Get(this); }
set { NameProperty.Set(this, value); }
}
}
And I almost have an implementation, but I can't quite get the info I need out of my NameProperty class.)
You can partially achieve (1-level of inheritance deep) using generics:
class PropertyBase<T>
{
public static Type GetMyType() { return typeof (T); }
}
// the base class is actually a generic specialized by the derived class type
class ConcreteProperty : PropertyBase<ConcreteProperty> { /* more code here */ }
// t == typeof(ConcreteProperty)
var t = ConcreteProperty.GetMyType();
The subclassing bit will not work, because a static method is tied to a type. It is a method of a type, not a method of an instance. The subtype does not contain the static methods of a base type, because they are different types and the static method is tied to the base type. Even though the compiler might allow you to call a static method of a base class as through a derived class, it will in reality call the method from the base class. It's just syntax sugar. For the same reason you cannot "override" static methods in subclasses because it would make little sense.
Just wondering why would need to do something like this?
var typeName = ConcreteProperty.GetMyType().Name;
Anyhow you know the type while calling the method, you can simply do this as well..
var typeName = typeof(ConcreteProperty).Name;
Just in case you need to do this, you can use "shadowing" to override the implementation of base class in child class.
public class ConcreteProperty : PropertyBase {
public new static Type GetMyType {
//provide a new implementation here
}
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why cannot C# generics derive from one of the generic type parameters like they can in C++ templates?
I can do
public class MyGenericClass : DL
//but i cannot do
public class MyGenericClass <T> : T
How would i do the second? if i cannot do that, how can i do something like
public class MyGenericClass <T>
{
T obj;
//have all MyGenericClass.XYZ call obj.XYZ
}
This is not possible, because depending on what type T is, the public interface of MyGenericClass would change.
If you have lots of different classes that all expose the same interface, you could declare MyGenericClass to expose that interface, and in the implementation of all of the functions delegate the calls to obj
The specific question, why can't you do this:
public class MyGenericClass<T> : T
And you can do this:
public class MyGenericClass<T>
{
T obj;
}
The reason is that the CLR likes to be able to compile a single version of the code for MyGenericClass that will work for any reference type specified for T.
It can do this for the second case, because it can quietly replace T with object and insert appropriate casts, roughly equivalent to:
public class MyGenericClass
{
object obj;
}
But for the inheritance version, that trick doesn't work.
Also, many useful facilities would be impossible to describe through interface constraints. When you inherit from a type, you can do a lot more than just call methods on it - you can override them as well. Consider this hypothetical example:
class MyBase
{
public virtual void MyVirtual() { }
}
class MyGenericDerived<T> : T
{
public override void MyVirtual()
{
Console.WriteLine("Overridden!");
}
}
MyBase obj = new MyGenericDerived<MyBase>();
obj.MyVirtual();
What I want to do there is something like a "mix-in", where MyGenericDerived supplies definitions for virtual functions in whatever base it is applied to. But how does the compiler know that T will have a method called MyVirtual that can be overridden? I'd need to put a constraint on T. How would I express that through interfaces? It's impossible. Using interfaces to describe constraints isn't an adequate solution once you allow inheritance from type parameters. So that's another reason why it doesn't exist in the language today.
You could do something like
public interface IXyzable { void xyz(); }
public class MyGenericClass<T> : IXyzable where T : IXyzable {
T obj;
public void xyz() {
obj.xyz();
}
}
Edit: Now I understand the question
You'll need all your possible T's to implement some interface so that you know that obj.XYZ() makes sense, then you can do
public interface Ixyz
{
void XYZ();
}
public class MyGenericClass<T> : Ixyz where T:Ixyz, new()
{
T obj;
public MyGenericClass()
{
obj = new T();
}
public void XYZ()
{
obj.XYZ();
}
}
I've made MyGenericClass implement Ixyz too since it obviously does expose the right method, but maybe that's best left out since it allows
var x = new MyGenericClass<MyGenericClass<SomeClass>>();
which is unlikely to ever be a good idea.
This is pretty much duck-typing, but you could use reflection.
When you create the generic class with a reference to the obj, use reflection to try and find a method with the right signature. As long as you store a reference to the method, performance won't be too bad.
class BaseGeneric<T>
{
private T obj;
private MethodInfo mi;
private const string MethodNameOfInterest = "Xyz";
public BaseGeneric(T theObject)
{
this.obj = theObject;
Type t = obj.GetType();
mi = t.GetMethod(MethodNameOfInterest);
}
public void Xyz()
{
mi.Invoke(obj, null);
}
}
Of course, you would need to add a lot more for error checking and such, but that is the gist of what you could do. Also, don't forget to add the System.Reflection namespace to your using clause.
The .NET type system won't allow type declarations of the form you're attempting. One reason why this is disallowed should be intuitive: how would MyGenericClass<T> act when T is a sealed class (e.g. System.String)?
If you absolutely need this functionality (and you know that the type T you'll be using isn't sealed), you can generate proxies at runtime using the classes in the Reflection.Emit namespace. It may also be possible to achieve this effect using AOP tools like PostSharp.
What about this:
class BaseClass<T>
{
public T property { get; set; }
}
class GenericClass<T> : BaseClass<T>
{
}
class Program
{
static void Main(string[] args)
{
GenericClass<int> l = new GenericClass<int>();
l.property = 10;
}
}
This achieves what you want to do?
I've made a test case to illustrate the problem I've run into.
The first assert passes, but the second and third both fail.
Is there a way to check either of the two failing conditions k in a different way that will work? It would be OK if it's not terribly fast as I intend to cache the results on a per-type basis.
public interface IParentInterface
{
}
public interface IChildInterface : IParentInterface
{
}
public class ParentClass<T> where T: IParentInterface
{
}
public class ChildClass : ParentClass<IChildInterface>
{
}
public class TestClass
{
public ChildClass Property { get; set; }
}
[TestFixture]
public class ScratchPad
{
[Test]
public void Assignabl()
{
var tc = new TestClass();
var tct = tc.GetType();
var pi = tct.GetProperty("Property");
Assert.IsNotNull(pi);
Assert.IsTrue(typeof(ParentClass<IChildInterface>).IsAssignableFrom(pi.PropertyType));
Assert.IsTrue(typeof(ParentClass<>).IsAssignableFrom(pi.PropertyType));
Assert.IsTrue(typeof(ParentClass<IParentInterface>).IsAssignableFrom(pi.PropertyType));
}
}
It is by design that your second assertion fails. When you write
public class ParentClass<ParentInterface>
it actually means that "ParentInterface" is now a symbol for a type argument (doing that is so confusing that, indeed, it totally confused you).
Writing
public class ChildClass : ParentClass<ChildInterface>
then sets yout type argument (yeah, the one named "ParentInterface") to the type ChildInterface. Hence, Childclass is only assignable to ParentClass<ChildInterface>.
Lastly, you should ensure that you follow conventions when definining type arguments, it will confuse you a lot less, e.g.
public class ParentClass<T>
marking interfaces with "I" will also greatly enhance understanding, e.g.
interface IParent { }
interface IChild : IParent { }
I suspect that that which you want is not possible until we get c# 4.0:
Parent<IChild>
is not assignable to
Parent<IParent>
There is currently no co/contravariance for generics.
Isn't this the covariance/contravariance thing?
Then it's just something C# currently does not support, but C# 4.0 might.
You can't, because C# 3.0 does not support variance of this kind. In C# 4.0, you should be able to.
Using another example, say you had a List<ParentInterface>, and could assign it to a List<ChildInterface>:
List<ParentInterface> parentList = List<ParentInterface>();
List<ChildInterface> childList = parentList;
The problem is that the internal storage for parentList is for ParentInterface types. If you derived another interface from ChildInterface:
public interface ParentInterface2 : ChildInterface {}
And then tried to add it to childList like so:
childList.Add(new ParentInterface2Implementation());
You would get an exception, since childList is really a List<ParentInterface> and can only store implementations of ParentInterface, which ParentInterface2 is not.