I came across the following code, all in a single file/class. I'm leaving out the details, its the construct I'm interested in. Why are there two different declarations for the same class and how are they different? What's the purpose of the syntax for the second declaration?
public abstract class MyClass
{
...
}
public abstract class MyClass<TMyClass> : MyClass
where TMyClass: MyClass<TMyClass>
{
...
}
MyClass - A abstract class named MyClass.
MyClass<TMyClass> : MyClass - A abstract generic class named MyClass<> but with a generic type named TMyClass.
If you rename the types, it will be easier to see:
public abstract class MyBaseClass
{
...
}
public abstract class MyClass<T> : MyBaseClass
where T: MyClass<T>
{
...
}
Types with different generic arity (i.e. number of generic type parameters, which can be zero or more) are considered as completely unrelated by the language and can have the same name.
This means that you can have classes Foo, Foo<T> and Foo<T,U> at the same time; the syntax will allow the compiler to determine which you are referring to. You can see this happen in the base framework which includes Action, Action<T> etc.
The "recursive" construct class C<T> where T: C<T> (the inheritance from a non-generic C does not change anything so I removed it) is the C# on what is called the Curiously Recurring Template Pattern (CRTP) in C++. Eric Lippert has covered this subject very well in a blog post, where the conclusion is that one should think more than twice before implementing this -- there are problems it can solve, but the solution also has a price.
public abstract class MyClass<TMyClass> : MyClass
where TMyClass: MyClass<TMyClass>
{
...
}
is a class that inherits from MyClass, and it takes a generic type, which has to inherit from MyClass<TMyClass>
Here's a simpler example of the same thing for you
public static void Main()
{
MyClass<Myclass> other = new MyClass<Myclass>(new Myclass());
List<int> intlist = new List<int>();
}
public class Myclass
{
public Myclass()
{
}
public int i { get; set; }
}
public class MyClass<T> where T : Myclass
{
T value;
public MyClass(T val)
{
value = val;
}
}
}
It's a classic idiom, the Curiously Recurring Template Pattern, done in C#.
It means the template can only be used thusly:
class Foo : MyClass<Foo>
{
}
In this construction, Foo inherits MyClass<Foo> which inherits MyClass.
This has a few advantages, but I've forgotten which.
public abstract class MyClass<TMyClass> : MyClass
where TMyClass: MyClass<TMyClass>
{
...
}
First thing to point out is that this is an abstract class that is inheriting from another abstract class. In other words, this is a class that cannot be instantiated (without another class inheriting from it), but is using inheritence to derive the functionality from another abstract class (which is fine).
The second thing to point out, is that this is a Template class (or generic class as they call it in C#) which accepts type in it's . I would reduce that to T as a convention so that T is always a template, though it is completely up to you what you call things.
Lastly there is a constraint on this which is kind of strange. It says that, no matter what, the compiler will not allow any class type to be passed in as a template type, unless it inherits from (somewhere along the inheritance chain)
MyClass<TMyClass>
This is shown in the following line
where TMyClass: MyClass<TMyClass>
basically this prevents anyone from passing in an object that does not follow this rule.
What is a bit odd is that the constraints tells the implementer that it cannot be a template unless the type passed by template is in fact a type of itself. You as the designer of this class (or implementer) has to decide if this is a wise design, though this in itself looks a bit strange.
Related
I have the following code:
internal abstract class Base
{
internal abstract object Method1();
}
internal abstract class Base<T> : Base
{
new internal abstract T Method1();
}
I have no idea why this is able to compile. Here are my questions:
Why am I able in a derived class to define another abstract method which differs only by the returned type.
Why does the new modifier even work on abstract methods? At lest from my point of view it doesn't make any sense because Base has no implementation for it
Of course I'm not able to create any non abstract class that actually inherits from Base<T> but why was I able to do this in the first place?
After the first set of comments look like there's some room for improvement:
Why am I able in a derived class to define another abstract method
which differs only by the returned type.
This can be done even without the new keyword take for example:
class Program
{
static void Main(string[] args)
{
var obj = (Derived) new Object();
int result = obj.Method1();
}
}
internal abstract class Base1
{
internal abstract string Method1();
}
internal abstract class Derived: Base1
{
internal abstract int Method1();
}
The problems here are:
It is impossible to create a class which inherits from Derived
VS Intelisense tells you that there's an overload for that methods but it's just not able to display it.
While the answer might be that this doesn't make sense in the first place, I find this behavior a bit inconsistent because there are other places in the language when things which don't make sense cause a compile time error. An example is when trying to have a generic type constraint for a sealed or concrete value type.
As for my second question, it looks more like it's just a side effect of the first.
I first saw a colleague do this when he implemented object pools. He passed the class that was going to be pooled as a parameter to a generic base class. This base class layed out the pooling code.
The odd thing is that the base class will know of its children. This is considered bad practice in every normal case. But in this case the parent is just a technical solution to avoid writing repetetive code. The base class is never referenced by any other code.
One drawback with this construction is that it "burns the base class". You cannot introduce the generic base class in the middle of a hierarchy. This problem might be outside the topic.
Below is a thinkable example:
public abstract class Singleton<T> where T : class
{
public static T Instance { get; private set; }
public Singleton()
{
if (Instance != null)
throw new Exception("Singleton instance already created.");
Instance = (T) (object) this;
}
}
public class MyClass : Singleton<MyClass>
{
}
Improved code:
public abstract class Singleton<T> where T : Singleton<T>
{
public static T Instance { get; private set; }
public Singleton()
{
if (Instance != null)
throw new Exception("Singleton instance already created.");
Instance = (T) this;
}
}
public class MyClass : Singleton<MyClass>
{
}
No; this is a well-known pattern called the CRTP.
It is especially useful in C++ as an alternative to virtual methods.
You can see it inside the .Net framework in IComparable<T> and IEquatable<T>.
For added robustness, you should add where T : Singleton<T>
SLaks is correct - this is a useful pattern, generally for when you want to provide code in your base class which is strongly typed to your derived class.
You would also generally add a type constraint to the generic parameter to indicate that the generic type must inherit from the abstract type. The syntax for adding this constraint looks recursive, but don't panic about that - it is not evaluated recursively and simply ensures that the only valid generic types are derived classes.
For example, let's say you run a tea and coffee blending business. It makes sense for you to blend coffee with coffee, and tea with tea, but you want to make sure that you can't blend coffee with tea. However, as they are both beverages, you want to model them in the same way.
public abstract class Beverage<T> where T : Beverage<T>
{
public abstract T Blend(T drink1, T drink2);
}
public class Tea : Beverage<Tea>
{
public override Tea Blend(Tea drink1, Tea drink2)
{
// Blend tea here.
}
}
public class Coffee : Beverage<Coffee>
{
public override Coffee Blend(Coffee drink1, Coffee drink2)
{
// Blend coffee here. Although coffee is nasty, so
// why you'd want to is beyond me.
}
}
When reading about CRTP, it is worth remembering that C++ templates are only superficially similar to C# generics. The key difference is that templates are effectively a code generation tool which work at compile-time, whereas C# generics are supported at run time.
Furthermore, writing code like this can reduce readability. So although there are definitely instances where this would be the correct approach, you should take a think about the problem you're trying to solve and see if there's a more straightforward approach.
I have 2 classes with the following declarations:
abstract class ClassBase<T, S> where T : myType where S : System.Data.Objects.DataClasses.EntityObject
abstract class ServiceBase<T> where T : myType
and I have 2 other classes, that inherit one from each, we can call ClassInherited and ServiceInherited. Note that the two Service classes are not in the same project as the other two.
The idea is that in the ServiceBase class I can declare a property like protected ClassBase<T,System.Data.Objects.DataClasses.EntityObject> Class { get; set; } and then in the inherited service`s constructor something like this.Class = ClassInheritedInstance
I already implemented the idea but it gives me this error when assigning the Class property in the ServiceInherited class constructor:
Cannot implicitly convert type 'ClassInherited' to 'ClassBase< T, S>'
Note that ClassInherited is indeed an specification of Class<T,S>... it's just that the compiler doesn't seem to be able to tell the types correctly. Also changing the declaration of the class property to protected ClassBase<T, EntityObjectInherited> works, and EntityObjectInherited is an implementation of System.Data.Objects.DataClasses.EntityObject... I don't see why is there a problem.
Update 1
Note that at compile time the type of ClassInherited is known, as its declaration is public class ClassInherited : ClassBase<myTypeInherited, EntityObjectInherited>
INITIAL ANSWER
The reason that you cannot use protected ClassBase<T,S> Class { get; set; } in the ServiceInherited-class is that you do not know the S-type that is needed to declare a type of the property Class.
You have to options:
Include the S type in the specification of the Service-type: abstract class ServiceBase<T, S> where T : myType where S : System.Data.Objects.DataClasses.EntityObject
Implement an interface for ClassBase with only the T-type, so that you can refer to a class-inherited-object without using the S-type. Then you CAN have a property in the service class (of the interface-type), since you do not need to specify the S-type.
Note that generic-type-checking is not checked at run-time, but at compile-time. Else it wouldn't be strong-typing.
UPDATE
The reason the cast won't work is that type ClassBase<T, EntityObjectInherited> is not equal or castable to ClassBase<T, System.Data.Objects.DataClasses.EntityObject>. Covariance doesn't work on class-types, only on interface-types.
I think the solution here is to work with interfaces. Use an interface for class-base, say IClassBase<T>. That way you can omit the S-type in the signature of the class, and only have it in the interface.
UPDATE (2)
One thing you can do is to create an interface for the Class property. You can define the following interface.
public interface IClass<T> where T : myType {
// TODO
// Define some interface definition, but you cannot use the
// EntityObject derived class, since they are not to be known
// in the service class.
}
If you implement this interface on your ClassBase class, and add a constructor on your ServiceBase class which accepts an object of type IClass, then you can push this object to property Class in the base-class. Like this:
public abstract class ClassBase<T, S> : IClass<T>
where T : MyType
where S : EntityObject {
}
public abstract class ServiceBase<T> where T : MyType {
protected ServiceBase(IClass<T> classObject) {
Class = classObject;
}
protected IClass<T> Class { get; set; }
}
public class ServiceInherited : ServiceBase<MyTypeDerived> {
public ServiceInherited(IClass<MyTypeDerived> classObject)
: base(classObject) {
}
}
One thing to note, is not to expose the S-type of the ClassBase to the interface. Since you do not want the Service-classes to know this type, they cannot actively call any methods or use properties that somehow have the S-type in their definition.
This ugly boxing, unboxing should work :
Class = (ClassBase<T, S>)(object)new ClassInherited();
Covariance is allowed only with generic interface today ?MSDN
This works :
// Covariance.
IEnumerable<string> strings = new List<string>();
// An object that is instantiated with a more derived type argument
// is assigned to an object instantiated with a less derived type argument.
// Assignment compatibility is preserved.
IEnumerable<object> objects = strings;
This doesn't :
List<string> strings = new List<string>();
List<object> objects = strings;
The compiler won't be able to guess that ClassInherited is indeed a correct match for ClassBase<T, S> as it does not know the exact types of T and S, that will be decided at generics type instanciation at runtime.
So if you're sure that at runtime the types will be compatible you can safely try a cast :
Class = ClassInheritedInstance as ClassBase<T, S>
This will only have a slight (not to say negligible) overhead as the CLR will need to check the compatibility of the types to have safe code.
I'm writing two APIs that I will use with many of my projects. Some projects my use one of the APIs, some the other, but the majority of my projects will use both. I'm trying to design them as if they're completely separate, but I'm struggling on one thing.
namespace FirstApi {
public abstract class MyBaseClass {
//constructor, some methods and properties
public IEnumerable<T> Search<T>() where T : MyBaseClass, new() {
//search logic here. must use generics as I create new instances of T here
}
}
}
namespace SecondApi {
public interface IMyInterface {
//some property and method signatures
IEnumerable<T> Search<T>() where T : IMyInterface, new();
}
}
namespace MyProject {
public class MyDerivedClass : MyBaseClass, IMyInterface {
}
}
Both APIs require this search method. The second API has some functionality in other classes that calls IMyInterface.Search<T>(), and I would like those classes that inherit MyBaseClass to use the Search<T> function defined in MyBaseClass.
Compilation error: The constraints for type parameter 'T' of method 'MyBaseClass.Search()' must match the constraints for type parameter 'T' of interface method 'IMyInterface.Search()'. Consider using an explicit interface implementation instead.
Note: When Search is called, T will always be the derived class of whichever abstract class or interface has been inherited. This was the only way I could find of achieving this in C# 2.0 (C# abstract class return derived type enumerator), and it's just caused more problems!
Is there a type-safe way that I can achieve this, without using objects and casting?
Solution:
Based on the accepted answer by Andras Zoltan, I created this class in my project, and will have to re-create this class for each project that uses both APIs.
public abstract class ApiAdapter<TAdapter> : MyBaseClass, IMyInterface where TAdapter: MyBaseClass, IJsonObject, new()
{
IEnumerable<T> IJsonObject.Search<T>()
{
foreach (TAdapter row in base.Search<TAdapter>())
yield return (T)(IMyInterface)row;
}
}
I then inherit this class like so.
public class Client : ApiAdapter<Client> {
//everything else can go here
}
You can explicitly implement the interfaces Search method, e.g.
public class MyDerivedClass : BasicTestApp.FirstApi.MyBaseClass, BasicTestApp.SecondApi.IMyInterface
{
IEnumerable<T> SecondApi.IMyInterface.Search<T>()
{
// do implementation
}
}
However, I think you are asking for the MyBaseClass Search method to be called when the part of the code that handles your object as IMyInterface calls the Search<T> method. I cannot see a way because you have two T types with different constraints that cannot be related.
If you did where T : BasicTestApp.FirstApi.MyBaseClass, IMyInterface, new(); in both definitions of the Search method then you would not have a problem but this would tie both your APIs together
Here is a possible implementation of your explicitly implemented interface method. It doesn't avoid the cast but at least keeps it neat.
IEnumerable<T> SecondApi.IMyInterface.Search<T>()
{
var results = base.Search<MyDerivedClass>();
return results.Cast<T>();
}
I started my answer with exposition on why it's not working for you, but I think that's well understood now so I'll leave it out.
I've upvoted #IndigoDelta's answer but it highlights something I don't like about the overall design here - I have a sneaking suspicion you should actually be using a generic interface and generic class; not generic methods because it doesn't make any sense that:
Note: When Search is called, T will always be the derived class of whichever abstract class or interface has been inherited.
I'm throwing this solution into the mix; which I think is better because it means that each derived type doesn't need to reimplement the IMyInterface.Search method, and it goes some way to actually enforcing this rule you mention. It's a generic type dedicated to join the two APIs together, meaning the derived types don't need to do anything:
namespace MyProject
{
using FirstApi;
using SecondApi;
public class SecondAPIAdapter<T2> : MyBaseClass, IMyInterface
where T2 : SecondAPIAdapter<T2>, new()
{
#region IMyInterface Members
IEnumerable<T> IMyInterface.Search<T>()
{
return Search<T2>().Cast<T>();
}
#endregion
}
//now you simply derive from the APIAdapter class - passing
//in your derived type as the generic parameter.
public class MyDerivedClass : SecondAPIAdapter<MyDerivedClass>
{ }
}
i think you can do explicit implementation of interface and when you will access methor thru IMyInterface.Search - compiler will run the right method.
You need to use an explicit implementation.
public class MyDerivedClass : MyBaseClass, IMyInterface
{
// The base class implementation of Search inherited
IEnumerable<T> IMyInterface.Search<T>()
{
// The interface implementation
throw new NotImplementedException();
// this would not work because base does not implement IMyInterface
return base.Search<T>();
}
}
Since the implementations are different this makes sense. If they are not different then either the base class should implement the interface and you should use covariance (.Net 4.0 only) to combine your contraints or, perhaps you don't need the interface at all.
I hope I'm not confused, could you not change your definitions, such that:
public interface IMyInterface<in T>
{
//some property and method signatures
IEnumerable<U> Search<U>() where U : T, new();
}
Providing a generic argument of T which can use to enforce that the implementation provides a search function constraint to types of T:
public abstract class MyBaseClass : IMyInterface<MyBaseClass>
{
public virtual IEnumerable<T> Search<T>() where T : MyBaseClass, new()
{
}
}
That way, your derived types are simply:
public class MyDerivedClass : MyBaseClass
{
}
Which you can then do searches as:
var derived = new MyDerivedClass();
IMyInterface<MyDerivedClass> iface = impl;
var results = iface.Search<MyDerivedClass>();
In c# we can't create an obeject of a abstact class or interface it means abstract class do not have any constructor, is it true ?
or if it have then what is it's purpose there?
As others have said, abstract classes usually have constructors (either explicitly or the default one created by the compiler) - and any derived class constructor will have to chain through the abstract class's constructor in the normal way. That's the important bit... suppose you have an abstract class which stores the name associated with an instance - because you always want a name, and you don't want to write the Name property in each concrete derived class. You might provide a constructor which takes that name and assigns it to a field... and then every subclass constructor would have to go through that constructor, so that you still knew you'd always have a name. If you want to know more about constructor chaining, read my article on it.
Here's an example of that:
public abstract class DemoBase
{
private readonly string name;
public string Name { get { return name; } }
protected DemoBase(string name)
{
this.name = name;
}
// Abstract members here, probably
}
public class FixedNameDemo : DemoBase
{
public FixedNameDemo()
: base ("Always the same name")
{
}
// Other stuff here
}
public class VariableNameDemo : DemoBase
{
public VariableNameDemo(string name)
: base(name)
{
}
// Other stuff here
}
To further answer your comment on BoltClock's answer, asbtract classes can't have private abstract methods, but they can have private constructors. Indeed, it's sometimes useful to have only private constructors in an abstract class, because it means the class can only be derived from within the program text of the same class. This allows you to create pseudo-enums:
public abstract class ArithmeticOperator
{
public static readonly ArithmeticOperator Plus = new PlusOperator();
public static readonly ArithmeticOperator Minus = new MinusOperator();
public abstract int Apply(int x, int y);
private ArithmeticOperator() {}
private class PlusOperator : ArithmeticOperator
{
public override int Apply(int x, int y)
{
return x + y;
}
}
private class MinusOperator : ArithmeticOperator
{
public override int Apply(int x, int y)
{
return x - y;
}
}
}
In this respect, an abstract private method/property could make sense - it could be accessed by the base class but provided by the derived classes within the same class's program text. However, it's prohibited by the specification. Usually, protected abstract members would solve the same problem - but not quite always.
Good question. Here's why Abstract classes need constructors even though they cannot be instantited.
In any Object oriented language like C#, object construction is an hierarchical process. Look at the code below. When you instantiate any object of type DerivedClass, it must construct the base object first before creating the object of typeof DerivedClass. Here the base class may or may not be an Abstract class. But even when you instantiate an object of a concrete type derived from an abstract class it will still need to call the constructor of the Base class before the object of DerivedClass type is created, hence you always need a constructor for Abstract class. If you have not added any constructor, C# compiler will automatically add a public parameterless constructor to the class in the generated MSIL.
public class BaseClass
{
public BaseClass()
{
Console.WriteLine("BaseClass constructor called..");
}
}
public class DerivedClass : BaseClass
{
public DerivedClass()
{
Console.WriteLine("DerivedClass constructor called..");
}
}
DerivedClass obj = new DerivedClass();
//Output
//BaseClass constructor called..
//DerivedClass constructor called..
PS: Assuming, If Abstract base classes
are not allowed to have constructors
because they need not be instantiated,
the whole fundamentals of the object
oriented programming will go on toss.
The idea behind Abstract types are to
represent objects that have some
features and behaviours but not
complete as whole to allow independant
existence.
No. it means that operator new is not allowed to create object from this type of class.
The purpose might be that are allocated/initialized some properties of class.
abstract usually leave some methods to implement.
Regarding the interface, this structure holds only the signatures of method, delegates or events. That may be implemented in class that use interface. You cant create a object.
Read about new
EDIT:
What is the purpose of constructor in abstract class ?
When one class inherit another class, the parent class of it had to be created first while object is crated. In class do not implement some special constructor always is used default one [className()]. When you override some method then the implementation of functionality is taken form class which override the method. This is why method used in constructor should never be virtual. Same logic for abstract class, such class can have a lot of functionality, and only one method that should be implemented by child class.
Abstract classes have constructors but you can't call them directly as you can't directly instantiate abstract classes.
To answer your comment, the concept of a private abstract method or property makes no sense, because private prevents anybody else from accessing it, and abstract prevents itself from accessing it. So there would essentially be no possible way to call it.
EDIT: see Jon Skeet's answer on private constructors. Private members of other kinds cannot exist in abstract classes, though.
Abstract classes do have constructors. When you create an instance of a derived class, its parent class' constructors are called. This applies to classes derived from abstract classes as well.