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.
Related
I want to implement a method like this with C# 7.3 to force some data transfer objects to comply with my implementation:
public List<T> QueryOnDb<T>(DateTime dateRef) where T : baseDTO
{
string param = T.getParam();
List<string> resultJson = _context.Foo.Where(x=> x.type == param).Select(x=> x.json).ToList();
return resultJson.Select(x => JsonConvert.DeserializeObject<T>(x)).ToList();
}
Obviously it won't compile, because C# does not support static abstract methods on a abstract class.
The first workaround I tought was to pass param on the signature of QueryOnDb, but I could have T and param different.
EDIT 1: added the mention that getParam() should be abstrat.
It's possible to use Reflection so that a call to a static method in a generic class will chain to a static method with a particular name in a derived class, if one exists, or use a programmed fallback action if none exists. It's not possible to make the compiler reject derived classes that fail to define a static method with a particular name, but that's not really any more of a problem than the broader inability of compilers to reject classes that violate their inheritance requirements in most other ways.
Although Reflection has a reputation for being slow, performance can be quite good if a generic class uses a static delegate to identify the function to be called. That delegate should be initialized to a function that will use Reflection to look up the static method in the class specified by the generic parameter, and store it in the delegate. Future calls can then use that delegate directly without having to look up the method again for that particular generic class.
I have an abstract class like this:
public abstract class BaseCamera<TCamera> : ICamera where TCamera : ManagedCameraBase
{
public static uint GetNumberOfCameras()
{
using (var bus = new ManagedBusManager())
{
bus.RescanBus();
return bus.GetNumOfCameras();
}
}
}
And want to call it like this:
BaseCamera.GetNumberOfCameras()
It makes sense to me, because since this is an abstract class, only the concrete children classes must choose a TCamera, and the base class wants to get the number of all cameras, no matter they type.
However, the compiler does not approve:
Using the Generic type 'BaseCamera' requires 1 type
arguments.
Is there some way around it or do I need to create a new class just for this?
I think it is worth pointing out that ManagedCameraBase is a class from an external API I'm wrapping. Therefore, I do not want to include it in any of my calls for BaseCamera and that is why I'm trying to avoid specifying a type.
because since this is an abstract class, only the concrete children classes must choose a TCamera
That's not how generics work. This has nothing at all to do with the class being abstract. If the class was generic and not abstract you would still need to specify a generic argument in order to call a static method of the class. On top of that, there's nothing to say that a child class can't also be generic. Yours may happen to not be, but there's nothing requiring that to be the case.
Now, in your particular case, the GetNumberOfCameras method doesn't use the generic argument (T) at all, so it doesn't matter what generic argument you provide, you can put in whatever you want and it'll work just fine. Of course, because of that, it's a sign that this method probably doesn't belong in this class; it should probably be in another class that this class also uses.
Here's the problem. The static method GetNumberOfCameras belongs to the class that contains it, but a generic class actually gets compiled into separate classes for each type. So, for example if you had this:
public class Foo<T>
{
static int foo = 0;
public static void IncrementFoo()
{
foo++;
}
public static int GetFoo()
{
return foo;
}
}
And then you did this:
Foo<string>.IncrementFoo();
Console.WriteLine(Foo<string>.GetFoo());
Console.WriteLine(Foo<int>.GetFoo());
You will see that the first call to GetFoo will return one, but the second will return zero. Foo<string>.GetFoo() and Foo<int>.GetFoo() are two separate static method that belong to two different classes (and access two different fields). So that's why you need a type. Otherwise the compiler won't know which static method of which class to call.
What you need is a non-generic base class for your generic class to inherit from. So if you do this:
public class Foo<T> : Foo
{
}
public class Foo
{
static int foo = 0;
public static void IncrementFoo()
{
foo++;
}
public static int GetFoo()
{
return foo;
}
}
Then this:
Foo<string>.IncrementFoo();
Console.WriteLine(Foo<string>.GetFoo());
Console.WriteLine(Foo<int>.GetFoo());
Will give you what you might have expected at first. In other words, both calls to GetFoo will return the same result. And, of course, you don't actually need the type argument anymore and can just do:
Foo.IncrementFoo();
Or course, the alternative is to just move your static methods into an entirely different class if there's no reason why it should be part of BaseCamera
Well, there are a couple of things here you need to understand better.
First of all, I see a problem with your design. The method you are attempting to stick into this class really has nothing to do with the generic nature of it. In fact, you are instantiating another class to do the job so it really does not belong here at all.
If it actually had something to do with an object that inherits from ManagedCameraBase, the method would probably not need to be static but rather an instance method. You can then decide on the accessor (public/private) based on usage.
Finally, you need to understand what Generics actually do under the covers. When you use the generic base with a particular type, an underlying specialized type is created for you behind the scenes by the compiler. If you were to use the static method, the compiler would need to know the type you are targeting in order to create the static instance that will serve your call. Because of this, if you call the static method, you must pass a type and you will end up with as many static instances as the types you use to call it (the types must derive from ManagedCameraBase, of course).
As you can see, you should either move that method out to some helper class or something of the sort, or make it a non-static, instance 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.
Consider the following program:
class A
{
public static void Foo()
{
}
}
static class Ext
{
public static void Foo(this A a)
{
}
}
class Program
{
static void Main(string[] args)
{
var a = new A();
a.Foo();
}
}
This fails to compile, with the error:
Member 'Test.A.Foo()' cannot be accessed with an instance reference; qualify it with a type name instead
Why is the compiler ignoring the extension method?
What you are trying to do isn't allowed. The C# MSDN Extension Method Article specifically states that:
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.
Thank goodness it isn't allowed as that would just be awful to have to maintain.
EDIT: So people are saying that static methods aren't instance methods, which is correct. But try doing this:
class A
{
public static void Foo() {}
public void Foo() {}
}
That won't compile either because of a name ambiguity. That is exactly what would happen if you were allowed to use the extension method. It would introduce the exact same ambiguity. Now, given that one method is static and one is instance, should that mean that there is no ambiguity, perhaps. But at the current state it does introduce ambiguity which is yet another reason why it wouldn't be allowed.
Edit #2: From a comment #ErenErsonmez made:
However, as long as the extension method doesn't have the same signature as an instance method, I don't understand how it could ever cause ambiguity with a static method
If you change the signature of the extension method it will definitely work. So the following will work:
class A
{
public static void Foo() { }
}
static class Ext
{
public static void Foo(this A me, int i)
{ }
}
class Program
{
static void Main(string[] args)
{
A a = new A();
a.Foo(10);
Console.ReadLine();
}
}
So it looks more like the issue is an ambiguity one and not that there can't ever be an extension method of the same name as a method that already exists.
The problem is overload resolution: The static method Foo() is a candidate, it is applicable - just choosing it as best match will cause an error - which is exactly what happens. Extension methods are only candidates for overload resolution after all other candidates have been considered. In the case of OPs problem case the extension method will not even have been considered before the error occurs.
It appears from this MSDN article that this is due to security concerns.
I have often heard the concern that extension methods can be used to
hijack or subvert the intended behavior of existing methods. Visual
Basic addresses this by ensuring that, wherever possible, an instance
method is preferable over an extension method.
The language allows extension methods to be used to create overloads
for existing instance methods with different signatures. This allows
extension methods to be used to create overloads, while preventing the
existing instance method from being overridden. If an extension method
exists with the same signature as an instance method, the shadowing
rules that are built into the compiler will prefer the instance
method, therefore eliminating the possibility of an extension method
overriding existing base class instance functionality
This is VB focused (and instance focused), but still, the general idea is there. Basically, the extension method takes the lowest precedence so that methods cannot be hijacked, and since the class already has a method signature for what you are trying to do, that takes precedence and throws the standard extension method error (when trying to call from an instance object). You can never have two methods with the same signature, and that is what you are asking to be attempted here essentially...and allowing it would be a security concern as explained above already.
Then, add the confusion that will be created by this, and it is just a bad idea to allow it.
In C#, I have base class Product and derived class Widget.
Product contains a static method MyMethod().
I want to call static method Product.MyMethod() from static method Widget.MyMethod().
I can't use the base keyword, because that only works with instance methods.
I can call Product.MyMethod() explicitly, but if I later change Widget to derive from another class, I have to revise the method.
Is there some syntax in C# similar to base that allows me to call a static method from a base class from a static method of a derived class?
static methods are basically a method to fallback from object oriented concepts. As a consequence, they are not very flexible in inheritance hierarchies and it's not possible to do such a thing directly.
The closest thing I can think of is a using directive.
using mybaseclass = Namespace.BaseClass;
class MyClass : mybaseclass {
static void MyMethod() { mybaseclass.BaseStaticMethod(); }
}
It can be done, but I don't recommend it.
public class Parent1
{
public static void Foo()
{
Console.WriteLine("Parent1");
}
}
public class Child : Parent1
{
public new static void Foo()
{
Type parent = typeof(Child).BaseType;
MethodInfo[] methods = parent.GetMethods();
MethodInfo foo = methods.First(m => m.Name == "Foo");
foo.Invoke(null, null);
}
}
Calling a static method using reflection is exactly the same as calling an instance method except that you pass null for the instance. You need FlattenHierarchy because it's defined in an ancestor.
var type = assy.GetType("MyNamespace.MyType");
MethodInfo mi = type.GetMethod("MyStaticMethod",
BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);
mi.Invoke(null, null);
Further reading and thinking leaves me asking the same questions as others who have responded: why use static methods like this? Are you trying to do functional programming, and if so why not use lambda expressions instead? If you want polymophic behaviours with shared state, instance methods would be better.
It can be done:
public class Parent1
{
protected static void Foo()
{
Console.WriteLine("Parent1");
}
}
public class Child : Parent1
{
public static void Foo()
{
return Parent1.Foo();
}
}
Can be useful for unit testing protected static methods (for example).
First and foremost, if you're worried about re-parenting a class, then you're probably doing inheritance wrong. Inheritance should be used to establish "is-a" relationships, not simply foster code reuse. If you need code re-use alone, consider using delegation, rather than inheritance. I suppose you could introduce an intermediate type between a sub-type and its parent, but I would let that possibility drive my design.
Second, if you need to use functionality from the base class but extend it AND the use case calls for a static method, then you might want to consider using some external class to hold the functionality. The classic case for this in my mind is the Factory pattern. One way to implement the Factory pattern is through Factory Methods, a static method on a class that constructs an instance of that class. Usually the constructor is protected so that the factory method is the only way to build the class from outside.
One way to approach re-use with Factory Methods in an inheritance hierarchy would be to put the common code in a protected method and call that method from the Factory Method rather than directly call the base class Factory Method from a sub-types Factory Method. A better implementation might use the same technique but move the Factory Methods to a Factory class and use the constructor logic (internal now, not private), perhaps in conjunction with an initialization method(s), to create the object. If the behavior you are inheriting is external from the class (decryption/validation/etc), you can use shared methods (or composition) within the Factory to allow re-use between the Factory methods.
Without knowing the goal of your use of static methods it's difficult to give you an exact direction, but hopefully this will help.
Static methods are not polymorphic, so what you want to do is impossible.
Trying to find a way to treat static methods as polymorphic is possible but dangerous, because the language itself doesn't support it.
Some suggestions:
Reflection
Aliasing the base class (such as Mehrdad's example)
Having into account that a Static method shoudn't relay in instance data... you should have a static "MyMethod" that behaves diferent based on a parameter or something like that.
Remember that the static method defined in one class is just a way to order your code... but it is the same if that method is placed elsewhere... because it don't relay on the object where it is placed.
EDIT: I think your best choise is to use Product.MyMethod explicitly... If you think it... it should't be probable that your Widget change its base clase... and also in that case it is a minor change in code.
Static methods are "Class-Level" methods. They are intended to be methods that apply to all instances of a specific class. Thus, inheritance of this method does not make sense as it would change the meaning to apply to instances of the class. For instance, if you were looping through a collection of Products (some of Widget, some not) and called MyMethod on each Product then the method that was called would be determined by the instance of the class. This violates the purpose of static methods.
You can probably do something like you want more cleanly by simply not using static methods at all, because in your example it does not seem like MyMethod applies to all instances of Product. However, you can achieve the same affect you are describing by using an interface class like ‘IMyMethod’. This approach is still not using a static method. I guess I’m not seeing a need for a static method. Why do you want to use a static method to begin with?
It's very simple. Much simpler than using aliasing, reflections, etc. Maybe it's been made easier in newer additions of .NET, IDK, but this works perfectly fine. Just like with instance methods, accessing base methods doesn't require base be used, it is optional, usually necessary when the inheriting and base class have a method of the same name. Even without the base keyword, you can access the static methods of a base class as if they were in the class you are calling from. I only tested this when calling a base static method from a derived class's static method. Might not work if you are calling from an instance method to a static method.
public class BaseThings
{
protected static void AssertPermissions()
{
//something
}
}
public class Person:BaseThings
{
public static void ValidatePerson(Person person)
{
//just call the base static method as if it were in this class.
AssertPermissions();
}
}