All of the examples for extension methods that I have seen consume the extension method in a class like:
class Program
{
static void Main()
{
...Call extension method here
}
}
These seem to work because the consuming class is static. Is there a way to consume an extension method in a non static class like below? I can't seem to find any examples like this.
I have my Extension Method class:
using System;
using System.Collections.Generic;
namespace AwesomeApp
{
public static class LinqExtensionMethods
{
public static IEnumerable<T> FindItemsBeforeAndAfter<T>(this IEnumerable<T> items, Predicate<T> matchFilling)
{
if (items == null)
throw new ArgumentNullException("items");
if (matchFilling == null)
throw new ArgumentNullException("matchFilling");
return items;
}
}
}
And I have my class that consumes the extention method
namespace AwesomeApp
{
public class Leaders : ILeaders
{
var leaders = GetAllLeaders();
var orderedleaders = leaders.OrderByDescending(o => o.PointsEarned);
var test = orderedleaders.FindItemsBeforeAndAfter(w => w.UserId == 1);
}
}
If I call the extension method from a static class I do not the the 'Extension method must be defined in a non-generic static class' error:
public class test
{
public void testfunc()
{
List<int> testlist = new List<int>() {1,2,3,4,5,6,7,8,9};
testlist.FindItemsBeforeAndAfter<int>(e => e == 5);
}
}
I have read through all the stackoverflow answers I can find on the non-generic static class error and they deal with writing your extension method but don't deal with consuming it.
So the question is: If using an extension method with a non-static class is not possible then is there any way to do something that works in a similar way? for example it can be called as .ExtensionMethod not Helper.ExtensionMethod(passedObject)??
Resolution: I thought I cut and pasted the extension method from public class Leaders : ILeaders to its own class so that I could make it static but I actually just copied it. The compiler error was pointing to the class name so I did not see the extension method still at the bottom of the file. The error message is accurate and everyone that answered is correct.
These seem to work because the consuming class is static.
No, that's incorrect. Extension methods definitely don't have to be consumed from static classes or static methods.
However, they do have to be declared in a class which is:
Non-nested
Non-generic
Static
You appear to be confusing calling with declaring - when you say:
If I call the extension method from a static class I do not the the 'Extension method must be defined in a non-generic static class' error
... you'll only get that if you try to declare the method in a class which doesn't satisfy all the above criteria. You should double click on the error to show where it's being generated - I'm sure you'll find it's the declaration, not the use of the method.
Note that your final example (class test) is not a static class, nor a static method.
Related
Why in a child class, i can not call the extention method defined for the derived class by calling the base class directly ( i get a compile error that the base class does not contain a definition for the extention method).
But instead, i can call the extention method without any compile errors when i call it directly from the child intance.
Below is the code for my question :
using System;
using System.Reflection;
public class Program
{
public static void Main()
{
Child child = new Child();
child.TestMethod();
}
}
// Derived class
public class Mother
{
}
// Child class
public class Child : Mother
{
public Child() : base()
{
}
public void TestMethod()
{
this.ExtentionMethod(3);// Ok: no compile errors
base.ExtentionMethod(3);// Ko: Compilation error (line 27, col 8): 'Mother' does not contain a definition for 'ExtentionMethod'
}
}
public static class Extender
{
public static void ExtentionMethod(this Mother mother, int i)
{
Console.WriteLine($"Mother extention method {i}");
}
}
When you call an extension method, the compiler looks at the type of the reference on the left and finds the most appropriate method. So when you call this.ExtentionMethod, the type of this is used to find the best method.
So in your case, the compiler will look for an extension with a Child first parameter. Since there is not one, it will then find the one with a Mother first parameter (since a Child "is-a" Mother).
Using base does not do a cast - it is used to access members of the base class. Since extension methods are not "members", base does not do what you expect it to do.
An alternative might be to cast this to the base class instead:
((Mother)this).ExtentionMethod(3);
Although I would note that you don't have a different extension method for the derived class, so with what you posted there would be no difference between this.ExtensionMethod and ((Mother)this).ExtensionBethod. The same method (with the same input values) are going to be called.
This an extension to D Stanley's answer.
If you had extension methods on both Mother, and Child, like this:
public static class Extender
{
public static void ExtentionMethod(this Mother mother, int i)
{
Console.WriteLine($"Mother extention method {i}");
}
public static void ExtentionMethod(this Child child, int i)
{
Console.WriteLine($"Child extention method {i}");
}
}
Then there is a distinction between calling it from the sub-class vs the base-class.
From inside Child
this.ExtentionMethod(3);
Will call the Child version.
((Mother)this).ExtentionMethod(3);
Will call the Mother version.
public void TestMethod()
{
this.ExtentionMethod(3);
((Mother)this).ExtentionMethod(3);
}
Would produce the following output with both extension methods from above:
child extention method 3
Mother extention method 3
The other answers offer very good explanations why you have problems, I'd like to make sure you know the fastest way out of that mess:
public void TestMethod()
{
this.ExtentionMethod(3);
Extender.ExtentionMethod((Mother)this, 3);
}
If your compiler does not recognize the extension method, just remove that syntactical sugar. You can still call it just like a regular, public static method and pass the parameters just as if the this keyword for exension methods never existed. It's not either or, you can still go the old way.
This shows http://msdn.microsoft.com/en-us/library/bb311042.aspx that a reference to a public static extension class in a public static namespace can be skipped.
However, it doesn't work with public static variables.
using UnityEngine;
using System.Collections;
namespace NDefault
{
public static class TDefault
{
public static int CNT=71;
public static bool has_method(this object target,string method_name)
{
return target.GetType().GetMethod(method_name)!=null;
}
}
}
_
using UnityEngine;
using System.Collections;
using NDefault;
public class TController :MonoBehaviour
{
void Start ()
{
int t;
print (t.has_method("GetType")); //This prints "True"
print (CNT);//This creates error "The name `CNT' does not exist in the current context"
}
void Update ()
{
}
}
Am I right, that for using static variables and methods without a class reference, I have to inherit all classes from a non-static default class containing them, while for extension methods I should create a separate static class in a namespace? I.e. I can't store them together?
You can have extension methods and regular static methods/properties in the same static class. For clarity it is best to separate them.
When accessing static properties/methods you must specify the class they belong to. So to access the CNT static property it would be
int cnt = TDefault.CNT;
in your case it would then be
print (TDefault.CNT);
This rule applies for extension methods as well. For extension methods, you must have a using statement for the namespace the extension method is defined in. You must also specify the object that the extension method is for. In your example, your extension methods works for all classes. This usually is not advised unless you are adding value to all classes. you usually want to specify a particular class
public static class Extensions
{
public static bool NewMethod(this MyObject source)
{
return true;
{
}
The method above will only be available on the MyObject class, and not other classes. Unlike "normal" static methods, extension methods require an instance of an object in order to work as "extension methods". Both samples below will work.
MyObject o = new MyObject();
bool val = o.NewMethod();
// this also will get the value
val = Extensions.NewMethod(o);
I have a class like this:
public class SomeClass
{
public static IEnumerable<SomeClass> GetOutput(IEnumerable<SomeClass> items)
{
//Do stuff
}
}
This class is not static, but I want to make GetOutput an extension method for IEnumerable<SomeClass>. As such, I create a new static class:
public static class SomeClassExtensionMethods
{
public static IEnumerable<SomeClass> GetOutput(this IEnumerable<SomeClass> items)
{
return SomeClass.GetOutput(items);
}
}
Is there any more elegant way to do this? Why aren't we allowed to make SomeClass.GetOutput an extension method?
There is no more elegant way to do this unfortunately.
Why they aren't allowed was already answered here: Why are extension methods only allowed in non-nested, non-generic static class?
GetOutput() has to be an instance method, and cannot be static if you wish to extend it.
Why aren't we allowed to make SomeClass.GetOutput an extension method?
You can but not with the standard C# tools.
To the C# compiler, an extension method for a type is a static method that takes an instance of that type as its first parameter and is marked with System.Runtime.CompilerServices.ExtensionAttribute.
When defining an extension method in C#, the C# compiler won't allow the application of that attribute at all, suggesting that you use the this syntax, which does have the cited requirements. So, you could define the SomeClass in some other language or use a tool that adds the attribute after the C# compiler is done.
PostSharp (non-free edition) can do that. Just mark GetOutput with a different attribute and write code to replace it with System.Runtime.CompilerServices.ExtensionAttribute.
public class SomeClass
{
[ExtensionAspect]
public static IEnumerable<SomeClass> GetOutput(IEnumerable<SomeClass> items)
{
return items;
}
}
GetOutput is marked with ExtensionAspectAttribute, which is derived from a PostSharp aspect. Post-processing during the build runs the ProvideAspect method, which adds the desired attribute.
[AttributeUsage(AttributeTargets.Method)]
public class ExtensionAspectAttribute : MethodLevelAspect, IAspectProvider
{
public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
{
var constructorInfo = typeof (System.Runtime.CompilerServices.ExtensionAttribute).GetConstructor(Type.EmptyTypes);
var objectConstruction = new ObjectConstruction(constructorInfo);
var aspectInstance = new CustomAttributeIntroductionAspect(objectConstruction);
yield return new AspectInstance(targetElement, aspectInstance);
}
}
So, in another project that references the binary assembly for SomeClass, this works:
var items = new [] { new SomeClass() };
var results = items.GetOutput();
That satisfies the C# compiler, however Intellisense doesn't see it as an extension method and ReSharper colors it as an error.
Of course, this is an academic exercise because there is little reason to not define the extension method in SomeClassExtensionMethods especially since it can be done in the same namespace and even the same .cs file as SomeClass.
I get the following compilation error at the class name.
Extension method must be defined in a non-generic static class
I am not using normal class. What could be the reason for this. I don't know and don't want to use extension methods.
As requested, here is my comment as an answer:
Without your code there isn't much we can do. My best guess is that you accidentally typed "this" somewhere in a parameter list.
Sample for extension method
public static class ExtensionMethods {
public static object ToAnOtherObject(this object obj) {
// Your operation here
}
}
I had the same problem, and solved it as follows. My code was something like this:
public static class ExtensionMethods
{
public static object ToAnOtherObject(this object obj)
{
// Your operation here
}
}
and I changed it to
public static class ExtensionMethods
{
public static object ToAnOtherObject(object obj)
{
// Your operation here
}
}
I removed the word "this" of the parameter of the method.
I'm guessing this relates to your previous list question; if so, the example I provided is an extension method, and would be:
public static class LinkedListUtils { // name doesn't matter, but must be
// static and non-generic
public static IEnumerable<T> Reverse<T>(this LinkedList<T> list) {...}
}
This utility class does not need to be the same as the consuming class, but extension methods is how it is possible to use as list.Reverse()
If you don't want it as an extension method, you can just make it a local static method - just take away the "this" from the firstparameter:
public static IEnumerable<T> Reverse<T>(LinkedList<T> list) {...}
and use as:
foreach(var val in Reverse(list)) {...}
The following points need to be considered when creating an extension method:
The class which defines an extension method must be non-generic and static
Every extension method must be a static method
The first parameter of the extension method should use the this keyword.
How about posting your code? Extension methods are declared by preceding the first parameter of a static method with this. Since you don't won't to use an extension method, I suspect you accidentally started a parameter list with this.
Look for something like:
void Method(this SomeType name)
{
}
This question already has answers here:
Can I add extension methods to an existing static class?
(18 answers)
Closed 1 year ago.
Can extension methods be applied to the class?
For example, extend DateTime to include a Tomorrow() method that could be invoked like:
DateTime.Tomorrow();
I know I can use
static DateTime Tomorrow(this Datetime value) { //... }
Or
public static MyClass {
public static Tomorrow() { //... }
}
for a similar result, but how can I extend DateTime so that I could invoke DateTime.Tomorrow?
Use an extension method.
Ex:
namespace ExtensionMethods
{
public static class MyExtensionMethods
{
public static DateTime Tomorrow(this DateTime date)
{
return date.AddDays(1);
}
}
}
Usage:
DateTime.Now.Tomorrow();
or
AnyObjectOfTypeDateTime.Tomorrow();
You cannot add methods to an existing type unless the existing type is marked as partial, you can only add methods that appear to be a member of the existing type through extension methods. Since this is the case you cannot add static methods to the type itself since extension methods use instances of that type.
There is nothing stopping you from creating your own static helper method like this:
static class DateTimeHelper
{
public static DateTime Tomorrow
{
get { return DateTime.Now.AddDays(1); }
}
}
Which you would use like this:
DateTime tomorrow = DateTimeHelper.Tomorrow;
Extension methods are syntactic sugar for making static methods whose first parameter is an instance of type T look as if they were an instance method on T.
As such the benefit is largely lost where you to make 'static extension methods' since they would serve to confuse the reader of the code even more than an extension method (since they appear to be fully qualified but are not actually defined in that class) for no syntactical gain (being able to chain calls in a fluent style within Linq for example).
Since you would have to bring the extensions into scope with a using anyway I would argue that it is simpler and safer to create:
public static class DateTimeUtils
{
public static DateTime Tomorrow { get { ... } }
}
And then use this in your code via:
WriteLine("{0}", DateTimeUtils.Tomorrow)
The closest I can get to the answer is by adding an extension method into a System.Type object. Not pretty, but still interesting.
public static class Foo
{
public static void Bar()
{
var now = DateTime.Now;
var tomorrow = typeof(DateTime).Tomorrow();
}
public static DateTime Tomorrow(this System.Type type)
{
if (type == typeof(DateTime)) {
return DateTime.Now.AddDays(1);
} else {
throw new InvalidOperationException();
}
}
}
Otherwise, IMO Andrew and ShuggyCoUk has a better implementation.
I would do the same as Kumu
namespace ExtensionMethods
{
public static class MyExtensionMethods
{
public static DateTime Tomorrow(this DateTime date)
{
return date.AddDays(1);
}
}
}
but call it like this new DateTime().Tomorrow();
Think it makes more seens than DateTime.Now.Tomorrow();
They provide the capability to extend existing types by adding new methods with no modifications necessary to the type. Calling methods from objects of the extended type within an application using instance method syntax is known as ‘‘extending’’ methods. Extension methods are not instance members on the type.
The key point to remember is that extension methods, defined as static methods, are in scope only when the namespace is explicitly imported into your application source code via the using directive. Even though extension methods are defined as static methods, they are still called using instance syntax.
Check the full example here
http://www.dotnetreaders.com/articles/Extension_methods_in_C-sharp.net,Methods_in_C_-sharp/201
Example:
class Extension
{
static void Main(string[] args)
{
string s = "sudhakar";
Console.WriteLine(s.GetWordCount());
Console.ReadLine();
}
}
public static class MyMathExtension
{
public static int GetWordCount(this System.String mystring)
{
return mystring.Length;
}
}
I was looking for something similar - a list of constraints on classes that provide Extension Methods. Seems tough to find a concise list so here goes:
You can't have any private or protected anything - fields, methods, etc.
It must be a static class, as in public static class....
Only methods can be in the class, and they must all be public static.
You can't have conventional static methods - ones that don't include a this argument aren't allowed.
All methods must begin:
public static ReturnType MethodName(this ClassName _this, ...)
So the first argument is always the this reference.
There is an implicit problem this creates - if you add methods that require a lock of any sort, you can't really provide it at the class level. Typically you'd provide a private instance-level lock, but it's not possible to add any private fields, leaving you with some very awkward options, like providing it as a public static on some outside class, etc. Gets dicey. Signs the C# language had kind of a bad turn in the design for these.
The workaround is to use your Extension Method class as just a Facade to a regular class, and all the static methods in your Extension class just call the real class, probably using a Singleton.
Unfortunately, you can't do that. I believe it would be useful, though. It is more natural to type:
DateTime.Tomorrow
than:
DateTimeUtil.Tomorrow
With a Util class, you have to check for the existence of a static method in two different classes, instead of one.
We have improved our answer with detail explanation.Now it's more easy to understand about extension method
Extension method: It is a mechanism through which we can extend the behavior of existing class without using the sub classing or modifying or recompiling the original class or struct.
We can extend our custom classes ,.net framework classes etc.
Extension method is actually a special kind of static method that is defined in the static class.
As DateTime class is already taken above and hence we have not taken this class for the explanation.
Below is the example
//This is a existing Calculator class which have only one method(Add)
public class Calculator
{
public double Add(double num1, double num2)
{
return num1 + num2;
}
}
// Below is the extension class which have one extension method.
public static class Extension
{
// It is extension method and it's first parameter is a calculator class.It's behavior is going to extend.
public static double Division(this Calculator cal, double num1,double num2){
return num1 / num2;
}
}
// We have tested the extension method below.
class Program
{
static void Main(string[] args)
{
Calculator cal = new Calculator();
double add=cal.Add(10, 10);
// It is a extension method in Calculator class.
double add=cal.Division(100, 10)
}
}