Extension Methods and method overriding - c#

The other day I found this statement in a stackoverflow post relating to Extension Methods:
The main thing there is ability to override different methods based on different generic’s parameters instantiation. This is similar to Haskell’s type classes
Java equivalent to C# extension methods
What's that supposed to mean? Can anybody give a significant example which clarifies this statement?

I'd assume that they're referring to the fact that C#'s compiler will choose the method that most narrowly defines the type. So for example if you have a abstract class (ABS) and a inherited class (CLS2) and 2 extension methods
public static object GetStuff(this ABS obj){
blah blah blah
}
public static object GetStuff(this CLS obj){
blah blah blah
}
if you call the CLS2.GetStuff() the compiler will choose the second method. Once you know that you can take "Override" an extension method by making it more specific. So if you have a generic class
public class Foo<T>{}
You could make 2 extension methods (using classes from above as types)
public static void DoSomething(this Foo<Abs> abs){}
and
public static void DoSomething(this Foo<CLS2> abs){}
Here the second method is "Overriding" the more "generic" abstract type.
This is ony possible with C# because it actually generates a new class for every Generic type. With a language like Java where it uses "Type Erasure Generics" you can't "overload" generic method since everything is really type Object under the hood.

Related

Parameter constraints - call method to check type in constraint?

I have a method with a generic parameter:
internal void DoSomething<T>(T workWithThis)
{
}
I now want to constrain this method to only accept parameters which inherit one of a few interfaces I'd like to specify. However I have not yet found a way to it. What I'd like looks like this:
internal void DoSomething<T>(T workWithThis) where T : ISomething | ISomethingElse
{
}
Obviously this is not working, so I tried it with a static method to check the Type of T:
public static bool CheckType(Type t)
{
return */check here*/
}
internal void DoSomething<T>(T workWithThis) where T : CheckType(typeof(T))
{
}
Obviously this is not going to work either. The question is why? Why is the compiler preventing me from doing that, based on my understanding there is no reason for it not to work
Why is the compiler preventing me from doing that, based on my understanding there is no reason for it not to work
The compiler is preventing you from doing it because you're trying to do something which isn't supported by C# as a language. The syntax you're trying to use does not comply with the productions in section 10.1.5 of the C# spec.
C# as a language simply does not support the scenario you require.
Now as for why the language doesn't allow this sort of flexibility - that comes down to the normal balancing act of:
How many developers would benefit from this and how much
Extra burden on other developers to understand a more complicated language
Resources (primarily within Microsoft) required to design the language feature, implement and test it
Oh, and of course this isn't just C# - the CLR would have to support such a restriction as well, and it would at least encourage other CLR languages to understand it too.
I suggest you solve this by having two separate methods. Note that they can't just be overloads of generic methods, as overloads cannot differ only by generic type constraints. If you don't mind about boxing for value types implementing the interface, you could overload with:
internal void DoSomething(ISomething something)
{
}
internal void DoSomething(ISomethingElse somethingElse)
{
}
... although then if you pass in a value where the expression is a type implementing both interfaces, you'll end up with overload ambiguity.
Alternatively, just give the two methods different names.
The compiler has to verify all the constraints at compile time, and cannot call a method to do so.
The only things you can specify in the where constraints are:
new() - require a parameterless constructor
class - must be a reference type
struct - must be a value type
SomeBaseClass
ISomeInterface
T : U - must be, inherit from, or implement one of the other generic parameters
See the C# Programming Guide - Constraints on Type Parameters for more information.
As for why, you should never have to answer "I see no reason for this to work". You have to start in the opposite direction, "Why should this work", and then come up with enough plausible and realistic scenarios and requirements to make it worthwhile to implement. See Minus 100 Points by Eric Gunnerson.
To fix this in your code, you should derive both interfaces from a common interface, and add a constraint on that instead.
If the two interfaces have nothing in common, then I question the benefit of actually adding a constraint in the first place.
For instance, if your code is going to call a method on the objects being used with the generic type/method, then obviously both interfaces have to have the same notion about what that method is, and the only way to do that would be for the method to be defined in a common base interface. That the two interfaces happen to have the same method or property declared, with the same signature, does not make it the same method.
Having said that, are you sure you even need generics here?
How about just declaring two methods, each taking one such interface?
internal void DoSomething(ISomething workWithThis)
internal void DoSomething(ISomethingElse workWithThis)
The compiler uses the generic constraint to determine what operations is available on T within the generic method - so allowing an or expression would not be type safe. For example you have two interfaces IFirst and ISecond:
public interface IFirst
{
void First();
}
public interface ISecond
{
void Second();
}
internal void DoSomething<T>(T workWithThis) where T : IFirst or ISecond
{
//How to call this method if the type is ISecond
workWithThis.First();
//How to call this method if the type is IFirst
workWithThis.Second();
}
You can define an empty interface that holds all of them.
Remember, that in C# interfaces can have multiple inheritance.
For example:
public interface IHolder : ISomething, ISomethingElse
{
}
and for generic
internal void DoSomething<T>(T workWithThis) where T : IHolder
{
}

What is difference between extension method and static method?

What is the difference between an extension method and a static method ?
I have two classes like this :
public static class AClass {
public static int AMethod(string ....)
{
}
}
and
public static class BClass {
public static int BMethod(this string ....)
{
}
}
I can use these like
AClass.AMethod('...');
or
'...'.BMethod();
Which is proposed ?
An extension method is still a static method. You can use it exactly as you'd use a normal static method.
The only difference is that an extension method allows you to use the method in a way that looks like it's part of the type, so you can write:
int result = stringValue.BMethod();
Instead of:
int result = BClass.BMethod(stringValue);
This works purely as a compile "trick" - the compiler sees the first form, and if the BClass is usable (it has a proper using and is in a referenced assembly), then it will turn it into the second method's IL for you. It's purely a convenience.
Which is proposed ?
This really depends. If you control the type, I'd recommend putting the methods on the type itself. This is typically more maintainable.
If you don't control the type, or you're trying to "extend" a common type (such as IEnumerable<T>), then extension methods may be a reasonable approach.
However, if the type is a very common type, I'd typically avoid extension methods, as they become "noise" in intellisense, which in turn can cause extra confusion. For example, I would personally not recommend adding extension methods on System.Object or System.String, etc.
You cannot override an extension method.
Only if the method has a different signature, then it can be overloaded.
Off course there are some limitations:
Extension Methods have to be implemented as static methods and in static classes (inside a non-nested, non-generic static class to be more precise).
You can use extension methods to extend a class or interface, but not to override them. An extension method with the same name and signature as an interface or class method will never be called. At compile time, extension methods always have lower priority than instance methods defined in the type itself.
Extension methods cannot access private variables in the type they are extending.
You can consider Extension Methods as a 'legal' way to add more static methods to existing classes without actually inheriting them.
But the funny thing is that unlike regular static methods of the class, you cannot call Extension Methods on a class level (you will get an compile time error if you try this), but instead you must invoke them on a instance of the class (as if they were some regular methods of the instance of that class, which they are not!!!).
Also, inside the Extension Method you can freely use public properties of the passed object instance on which the method is being invoked, you are by no means limited only to static object data. Only the Extension Method is static method, but the object on which is called is full, regular object instance.

What are we extending when creating a generic extension method?

public static class MyClass
{
public static void Print<T>(this T theObject)
{
Console.WriteLine("The print output is " + theObject.ToString());
}
}
In the given class I've specified a generic as the type to extend via the this keyword. Being that I've delayed the definition of the type until compile time, how does intellisense (and anything else involved) know what type I am extending? Does C# simply default to the top level System.Object?
Yes, it's System.Object unless you add a type constraint.
Being that I've delayed the definition of the type until compile time, how does intellisense (and anything else involved) know what type I am extending? Does C# simply default to the top level System.Object?
Those that say that this is an extension on System.Object are wrong. For one, this method will not box value type inputs, but an extension method defined on System.Object will.
The extension method you've defined is an generically parameterized extension method. It can be applied to any type that is valid as generic type parameter.
If you're not already thinking about extension methods in the following way, this might help you understand them a little bit better. Extension methods are just a trick that the language specification lets us get away with. Extension methods are really just static methods in static classes that we can call as if they were instance methods. So
static class Foo {
public static void M(this object obj) { }
}
is just a static method in a static class. You could call it like this:
Foo.M(obj);
but we can call it like it's an instance method:
obj.M();
Thus, when you have a generic extension method, stop for a minute and think about it as a static method in a static class
static class Foo {
public static void M<T>(this T obj) { }
}
You could call it like this:
object obj;
Foo.M(obj);
or you can call it like this:
obj.M();
There's no difference to the compiler which you write.
So, now you're thinking of it as a regular generic method. But surely when you think about it from this perspective you understand that the compiler will let you invoke this method on any type that is valid as a generic type parameter. And thus, you now understand why it can be thought of as an extension method on any type that is valid as a generic type parameter.

Static method in abstract class to return IEnumerable<DerivedType>

Is there a way of putting a static method in an abstract class that can return the derived type?
Does a static method even know what type it is even being called from in C#?
For example, a base class could be
public abstract class MyBase
{
public static IEnumerable<TDerivedType> LoadAll()
{
//functionality here
}
}
Then if MyDerivedType inherits MyBase, I'd like to be able to call MyDerivedType.LoadAll()
Nothing too important - I'm currently using a generic static method and calling MyBase.LoadAll<MyDerivedType>(), which works fine but it doesn't look quite as 'pretty' as this would be.
Static members aren't inherited, so the static method has to be told in some way what the derived type is. Your solution is one way. Another is the following:
public abstract class MyBase<T> where T : MyBase<T> {
public static IEnumerable<T> LoadAll() { }
}
Then:
class Derived : MyBase<Derived> { }
var all = MyBase<Derived>.LoadAll();
That said, I think there is something wrong with your model. MyBase represents something in your domain (of which they are more specific derived types) AND it knows how to load all of those objects? That's two responsibilities, and that ain't cool yo.
No, there currently isn't a way to do this. I'd possibly use a factory in this case
var all = MyClassFactory.LoadAll<MyDerivedType>();
An abstract class can never be instantiated(that's the whole point) so any static methods would have to be implemented in each child class.
From an MSDN Thread
Static methods can be defined in an abstract class. However, you cannot force a derived class to implement a static method. If you think about it, such a method would be useless. Static methods are invoked using type names, not instance variables. If I call MyBaseClass.MyMethod, then MyBaseClass.MyMethod will always be invoked. How would it do you any good to force MyChildClass, which inherits from MyBaseClass, to also a implement a static MyMethod?
(Note: edited implemented to instantiated in the first sentence.)
There is nothing wrong with the way you are doing this. In fact most of MS generic extension methods are designed like this.
As for:
"Does a static method even know what type it is even being called from in C#?"
Its not a question of the static method knowing, its a question of the compiler knowing. When the code is scanned by the compiler this is when all the types are consolidated. At this point it can work out what code calls what functions and what types need to be returned. This is also the reason that a var type cannot be returned from a function.

Why is it impossible to declare extension methods in a generic static class?

I'd like to create a lot of extension methods for some generic class, e.g. for
public class SimpleLinkedList<T> where T:IComparable
And I've started creating methods like this:
public static class LinkedListExtensions
{
public static T[] ToArray<T>(this SimpleLinkedList<T> simpleLinkedList) where T:IComparable
{
//// code
}
}
But when I tried to make LinkedListExtensions class generic like this:
public static class LinkedListExtensions<T> where T:IComparable
{
public static T[] ToArray(this SimpleLinkedList<T> simpleLinkedList)
{
////code
}
}
I get "Extension methods can only be declared in non-generic, non-nested static class".
And I'm trying to guess where this restriction came from and have no ideas.
EDIT: Still don't have clear vision of the problem. It seems like this was just not implemented for some reason.
Generally speaking, since you do not specify the class when you use an extension method, the compiler would have no way to know which is the class where the extension method is defined:
static class GenStatic<T>
{
static void ExtMeth(this Class c) {/*...*/}
}
Class c = new Class();
c.ExtMeth(); // Equivalent to GenStatic<T>.ExtMeth(c); what is T?
Since extension methods themselves can be generic, this is no real problem at all:
static class NonGenStatic
{
static void GenExtMeth<T>(this Class c) {/*...*/}
}
Class c = newClass();
c.ExtMeth<Class2>(); // Equivalent to NonGenStatic.ExtMeth<Class2>(c); OK
You can easily rewrite your example so that the static class is not generic, but the generic methods are. In fact, this is how .NET classes such as Enumerable are written.
public static class LinkedListExtensions
{
public static T[] ToArray<T>(this SimpleLinkedList<T> where T:IComparable simpleLinkedList)
{
// code
}
}
The problem is how does the compiler do the extension resolution?
Say you define both the methods you describe:
public static class LinkedListExtensions {
public static T[] ToArray<T>(this SimpleLinkedList<T> simpleLinkedList) where T:IComparable {
//// code
}
}
public static class LinkedListExtensions<T> where T:IComparable {
public static T[] ToArray(this SimpleLinkedList<T> simpleLinkedList) {
////code
}
}
Which method is used in the following case?
SimpleLinkedList<int> data = new SimpleLinkedList<int>();
int[] dataArray = data.ToArray();
My guess is that the language designers decided to restrict extension methods to the non-generic types to avoid this scenario.
A very interesting question, I have never been tempted to use static generic classes, but at least it seems possible.
In the context of declaring extension methods, you cannot only declare extension methods for a certain generic type (such as IEnumerable<T>) but also bring the type parameter T into the equation. If we agree to treat IEnumerable<int> and IEnumerable<string> as different types, this makes sense on a conceptual level too.
Being able to declare your extension methods in a static generic class would save you repeating your type parameter constraints over and over again, in effect grouping all extension methods for IEnumerable<T> where T : IComparable together.
According to the specification (citation needed), extension methods can only be declared in static not-nested and not-generic classes. The reason for the first two constraints are fairly obvious:
May not carry any state as it's not a mixin, just syntactic sugar.
Must have the same lexical scope as the type it provides extensions for.
The restriction on non-generic static classes seems a little arbitrary to me, I can't come up with a technical reason here. But it might be that the language designers decided to discourage you in writing extension methods that depend on the type parameter of a generic class you wish to provide extension methods for. Instead they want you to provide a truly generic implementation of your extension method but make it possible to provide optimized/specialized (compile-time bound) versions of your extension methods in addition to your general implementation.
Reminds me of template specialization in C++. EDIT: Unfortunately this is wrong, please see my additions below.
Ok, as this is a really interesting topic I did some further research. There actually is a technical restriction that I missed here. Let's look at some code:
public static class Test
{
public static void DoSomething<T>(this IEnumerable<T> source)
{
Console.WriteLine("general");
}
public static void DoSomething<T>(this IEnumerable<T> source) where T :IMyInterface
{
Console.WriteLine("specific");
}
}
This will actually fail with this compiler error:
Type 'ConsoleApplication1.Test'
already defines a member called
'DoSomething' with the same parameter
types
Ok, next we try splitting it up into two different extensions classes:
public interface IMyInterface { }
public class SomeType : IMyInterface {}
public static class TestSpecific
{
public static void DoSomething<T>(this IEnumerable<T> source) where T : IMyInterface
{
Console.WriteLine("specific");
}
}
public static class TestGeneral
{
public static void DoSomething<T>(this IEnumerable<T> source)
{
Console.WriteLine("general");
}
}
class Program
{
static void Main(string[] args)
{
var general = new List<int>();
var specific = new List<SomeType>();
general.DoSomething();
specific.DoSomething();
Console.ReadLine();
}
}
Against my initial impression (it was late yesterday night), this will result in an ambiguity at the call sites. To resolve this ambiguity one would need to call the extension method in a traditional way, but that's against our intention.
So this leaves us with a situation where it's not possible to declare compile-time bound generic specializations of extension methods. On the other hand, there is still no reason why we couldn't declare extension methods only for a single special generic type parameter. Therefore it'd be nice to declare them in a static generic class.
On the other hand writing an extension method like:
public static void DoSomething<T>(this IEnumerable<T> source) where T : IMyInterface {}
or
public static void DoSomething(this IEnumerable<IMyInterface> source) {}
is not all too different and only requires a little casting on the call site vs. on the extension method side (you will probably implement some optimization that depends on the specific type, so you'd need to cast T to IMyInterface or whatever anyway). So the only reason I can come up with is again, the language designers want to encourage you in writing generic extensions only in a truly generic fashion.
Some interesting things could happen here if we take co/contravariance in to the equation, which are about to be introduced with C# 4.0.
Don't think of extension methods as being tied to the static class in which they are contained. Instead, think of them as being tied to a specific namespace. Therefore, the static class in which they are defined is simply a shell used to declare these methods within the namespace. And while you could very well write multiple classes for different types of extension methods, you shouldn't think of the class itself as anything more than a way to clearly group your extension methods.
Extension methods do not extend any attributes of the class in which they are contained. The signature of the method will define everything about the extension method. And while you could also call your method like this, LinkedListExtensions.ToArray(...), I do not believe that was the intent for extension methods. As such, I believe the framework creators probably created the restriction you ran into as a way to inform developers simply that extension methods are self-contained and are not directly tied to the class in which they reside.
Just a thought, but is there any reason you can't just derive from this class and add the extra methods to the specialization rather than writing a suite of extension methods? I am sure you have your reasons but just throwing that out there.
Static classes should be able to be defined as abstract. If they were able to do this, then you could specify that they could not be used directly, but must be inherited just like a regular class and then generic static classes would be doable for extension methods because you could define them in the abstract class, inherit from said class, and everything would work properly.
As it is right now, there are a ton of significant limitations with static classes, this just being one that really messes with the mojo in a lot of cases. Combined with the inability to have the compiler infer the return type and thus requiring you to enter the whole generic implementation to call generic functions that don't have all of the generics in the method signature makes this stuff aggravatingly weak and makes for a lot of typing that shouldn't need to be there.
(There is also the case where the second generic is defined in the definition of the first and it won't use it, even though it's obvious to infer as well at compile time. This one is super annoying because it is completely obvious.) MS has a TON of work on Generics that they could be doing to improve this stuff.

Categories

Resources