Extension method: Difference between revisions

Content deleted Content added
Bender the Bot (talk | contribs)
m External links: HTTP to HTTPS for Blogspot
 
(41 intermediate revisions by 27 users not shown)
Line 1:
{{Short description|Computer programming method type}}
{{See also|Monkey patch}}
 
{{essay|date=May 2013}}
{{More citations needed|date=September 2024}}
In [[object-oriented computer programming]], an '''extension method ''' is a [[Method (computer programming)|method]] added to an object after the original object was [[Compiler|compiled]]. The modified object is often a class, a prototype, or a type. Extension methods are features of some object-oriented programming languages. There is no syntactic difference between calling an extension method and calling a method declared in the type definition.<ref name="ms_ext">{{cite web|url=http://msdn.microsoft.com/en-us/library/bb383977.aspx|title=Extension Methods|publisher=Microsoft|accessdate=2008-11-23}}</ref>
 
Not all languages implement extension methods in an equally safe manner, however. For instance, languages such as C#, Java (via [http://manifold.systems/docs.html#the-extension-manifold Manifold], [https://projectlombok.org/features/experimental/ExtensionMethod Lombok], or [https://github.com/rogerkeays/fluent Fluent]), and Kotlin don't alter the extended class in any way, because doing so may break [[class hierarchy|class hierarchies]] and interfere with virtual method dispatching. Instead, these languages strictly implement extension methods statically and use [[static dispatch]]ing to invoke them.
In [[object-oriented computer programming]], an '''extension method ''' is a [[Method (computer programming)|method]] added to an object after the original object was [[Compiler|compiled]]. The modified object is often a class, a prototype or a type. Extension methods are features of some object-oriented programming languages. There is no syntactic difference between calling an extension method and calling a method declared in the type definition.<ref name="ms_ext">{{cite web|url=http://msdn.microsoft.com/en-us/library/bb383977.aspx|title=Extension Methods|publisher=Microsoft|accessdate=2008-11-23}}</ref>
 
[[Eric Lippert]], a principal developer on the C# compiler team, says "Extension methods certainly are not object-oriented."<ref>{{cite web|url=http://blogs.msdn.com/b/ericlippert/archive/2008/10/28/the-future-of-c-part-two.aspx|title=The Future of C#, Part Two - Fabulous Adventures In Coding|publisher=Microsoft}}</ref>
 
==Support in programming languages==
Extension methods are features of numerous languages including [[C Sharp (programming language)|C#]], [[Java (programming language)|Java]] via [http://manifold.systems/docs.html#the-extension-manifold Manifold] or [https://projectlombok.org/features/experimental/ExtensionMethod Lombok] or [https://github.com/rogerkeays/fluent Fluent], [[Gosu (programming language)|Gosu]], [[JavascriptJavaScript]], [[Oxygene (programming language)|Oxygene]], [[Ruby (programming language)|Ruby]], [[Smalltalk]], [[Kotlin (programming language)|Kotlin]], and[[Dart (programming language)|Dart]], [[VB.NET|Visual Basic.NET]], and [[Xojo]]. In dynamic languages like [[Python (programming language)|Python]], the concept of an extension method is unnecessary because classes (excluding built-in classes) can be extended without any special syntax (an approach known as "[[Monkey patch|monkey-patching]]", employed in libraries such as [[gevent]]).
 
In VB.NET and Oxygene, they are recognized by the presence of the "<code>extension</code>" keyword or attribute. In Xojo, the "<code>Extends</code>" keyword is used with global methods.
 
In C#, they're are implemented as static methods in static classes, with the first argument being of extended class and preceded by "<code>this</code>" keyword.
 
In Java, extension methods are added via [http://manifold.systems/ Manifold], a jar file added to the project's classpath. Similar to C#, a Java extension method is declared static in an [http://manifold.systems/docs.html#extension-classes @Extension] class where the first argument has the same type as the extended class and is annotated with <code>@This</code>. Alternatively, the [https://github.com/rogerkeays/fluent Fluent] plugin allows calling any static method as an extension method without using annotations, as long as the method signature matches.
In Smalltalk, any code can add a method to any class at any time, by sending a method creation message (such as <code>methodsFor:</code>) to the class the user wants to extend. The Smalltalk method category is conventionally named after the package that provides the extension, surrounded by asterisks. For example, when Etoys application code extends classes in the core library, the added methods are put in the <code>*etoys*</code> category.
 
In Smalltalk, any code can add a method to any class at any time, by sending a method creation message (such as <code>methodsFor:</code>) to the class the user wants to extend. The Smalltalk method category is conventionally named after the package that provides the extension, surrounded by asterisks. For example, when Etoys application code extends classes in the core library, the added methods are put in the <code>*etoys*</code> category.
In Ruby, like Smalltalk, there is no special language feature for extension, as Ruby allows classes to be re-opened at any time with the <code>class</code> keyword, in this case to add new methods. The Ruby community often describes an extension method as a kind of [[monkey patch]].
 
In Ruby, like Smalltalk, there is no special language feature for extension, as Ruby allows classes to be re-opened at any time with the <code>class</code> keyword, in this case to add new methods. The Ruby community often describes an extension method as a kind of [[monkey patch]]. There is also a newer feature for adding safe/local extensions to the objects, called [https://docs.ruby-lang.org/en/2.5.0/syntax/refinements_rdoc.html Refinements], but it is known to be less used.
In Swift, the <code>extension</code> keyword marks a class-like construct that allows the addition of methods, constructors, and fields to an existing class, including the ability to implement a new interface/protocol to the existing class.
 
In Swift, the <code>extension</code> keyword marks a class-like construct that allows the addition of methods, constructors, and fields to an existing class, including the ability to implement a new interface/protocol to the existing class.<ref>{{Cite web |title=Extensions — The Swift Programming Language (Swift 5.7) |url=https://docs.swift.org/swift-book/LanguageGuide/Extensions.html |access-date=2022-06-12 |website=docs.swift.org}}</ref>
 
==Extension methods as enabling feature==
Next to extension methods allowing code written by others to be extended as described below, extension methods enable patterns that are useful in their own right as well. The predominant reason why extension methods were introduced was [[Language Integrated Query]] (LINQ). Compiler support for extension methods allows deep integration of LINQ with old code just the same as with new code, as well as support for [[C Sharp syntax#Query syntax|query syntax]] which for the moment is unique to the primary [[Microsoft .NET]] languages.
 
<sourcesyntaxhighlight lang="csharp">
Console.WriteLine(new[] { Math.PI, Math.E }.Where(d => d > 3).Select(d => Math.Sin(d / 2)).Sum());
// Output:
// 1
</syntaxhighlight>
</source>
 
===Centralize common behavior===
Line 36 ⟶ 38:
Consider the following code and suppose it is the only code contained in a class library. Nevertheless, every implementor of the ILogger interface will gain the ability to write a formatted string, just by including a ''using MyCoolLogger'' statement, without having to implement it once and without being required to subclass a class library provided implementation of ILogger.
 
<sourcesyntaxhighlight lang="csharp">
namespace MyCoolLogger {;
 
public interface ILogger { void Write(string text); }
public static class LoggerExtensions {
{
public static void Write(this ILogger logger, string format, params object[] args) {
void if Write(logger !=string nulltext);
}
logger.Write(string.Format(format, args));
 
}
public static class LoggerExtensions {
{
public static void Write(this ILogger logger, string format, params object[] args) {
}{
if (logger != null)
logger.Write(string.Format(format, args));
}
}
</syntaxhighlight>
</source>
* use as :<sourcesyntaxhighlight lang="csharp">var logger = new MyLoggerImplementation();
logger.Write("{0}: {1}", "kiddo sais", "Mam mam mam mam ...");
logger.Write("{0}: {1}", "kiddo sais", "Ma ma ma ma... ");
Line 55 ⟶ 63:
logger.Write("{0}: {1}", "mamma sais", "WHAT?!?!!!");
logger.Write("{0}: {1}", "kiddo sais", "hi.");
</syntaxhighlight>
</source>
 
===Better loose coupling===
Line 67 ⟶ 75:
The following example uses Entity Framework and configures the TodoList class to be stored in the database table Lists and defines a primary and a foreign key. The code should be understood more or less as: "A TodoList has key TodoListID, its entity set name is Lists and it has many TodoItem's each of which has a required TodoList".
 
<sourcesyntaxhighlight lang="csharp">
public class TodoItemContext : DbContext
{
Line 83 ⟶ 91:
}
}
</syntaxhighlight>
</source>
 
===Productivity===
Consider for example [http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx IEnumerable] and note its simplicity - there is just one method, yet it is the basis of LINQ more or less. There are many implementionsimplementations of this interface in Microsoft .NET. Nevertheless, obviously, it would have been burdensome to require each of these implementations to implement the whole series of methods that are defined in the [http://msdn.microsoft.com/en-us/library/system.linq.aspx System.Linq namespace] to operate on IEnumerables, even though Microsoft has all the source code. Even worse, this would have required everybody besides Microsoft considering to use IEnumerable themselves to also implement all those methods, which would have been very anti-productive seeing the widespread use of this very common interface. Instead, by implementing the one method of this interface, LINQ can be used more or less immediately. Especially seeing in practically most cases IEnumerable's GetEnumerator method is delegated to a private collection, list or array's GetEnumerator implementation.
 
<sourcesyntaxhighlight lang="csharp">
public class BankAccount : IEnumerable<decimal>
{
Line 107 ⟶ 115:
// one could now write ba.Sum() to get the account balance, ba.Reverse() to see most recent transactions first,
// ba.Average() to get the average amount per transaction, etcetera - without ever writing down an arithmetic operator
</syntaxhighlight>
</source>
 
===Performance===
Line 113 ⟶ 121:
 
===Alleviating the need for a common base class===
With generic classes, extension methods allow implementation of behavior that is available for all instantiations of the generic type without requiring them to derive from a common base class, and without restricting the type parameters to a specific inheritance branch. This is a big win, since the situations where this argument holds require a non-generic base class just to implement the shared feature - which then requires the generic subclass to perform [[boxing (programming)|boxing]] and/or casts whenever the type used is one of the type arguments.
 
===Conservative use===
A note should be placed on preferring extension methods over other means of achieving reuse and proper object -oriented design.
Extension methods might 'clutter' the automatic completion features of code editors, such as Visual Studio's IntelliSense, hence they should either be in their own namespace to allow the developer to selectively import them or they should be defined on a type that is specific enough for the method to appear in IntelliSense only when really relevant and given the above, consider that they might be hard to find should the developer expect them, but miss them from IntelliSense due to a missing using statement, since the developer may not have associated the method with the class that defines it, or even the namespace in which it lives - but rather with the type that it extends and the namespace that type lives in.
 
Line 123 ⟶ 131:
# Inherit the class and then implement the functionality in an instance method in the derived class.
# Implement the functionality in a static method added to a helper class.
# Use [[Object composition#Aggregation|aggregation]] instead of [[inheritance (computerobject-oriented scienceprogramming)|inheritance]].
 
==Current C# solutions==
Line 129 ⟶ 137:
 
As an example, consider a need of extending the string class with a new reverse method whose return value is a string with the characters in reversed order. Because the string class is a sealed type, the method would typically be added to a new [[utility class]] in a manner similar to the following:
<sourcesyntaxhighlight lang="csharp">
string x = "some string value";
string y = Utility.Reverse(x);
</syntaxhighlight>
</source>
 
This may, however, become increasingly difficult to navigate as the library of utility methods and classes increases, particularly for newcomers. The ___location is also less intuitive because, unlike most string methods, it would not be a member of the string class, but in a completely different class altogether. A better syntax would therefore be the following:
<sourcesyntaxhighlight lang="csharp">
string x = "some string value";
string y = x.Reverse();
</syntaxhighlight>
</source>
 
==Current VB.NET solutions==
In most ways, the VB.NET solution is similar to the C# solution above. However VB.NET has a unique advantage in that it allows members to be passed in to the extension by reference (C# only allows by value). Allowing for the following;
<sourcesyntaxhighlight lang="vbvbnet">
Dim x As String = "some string value"
x.Reverse()
</syntaxhighlight>
</source>
 
Because Visual Basic allows the source object to be passed in by reference it is possible to make changes to the source object directly, without need to create another variable. It is also more intuitive as it works in a consistent fashion to existing methods of classes.
Line 152 ⟶ 160:
The new language feature of extension methods in C# 3.0, however, makes the latter code possible. This approach requires a static class and a static method, as follows.
 
<sourcesyntaxhighlight lang="csharp">
public static class Utility
{
Line 162 ⟶ 170:
}
}
</syntaxhighlight>
</source>
 
In the definition, the modifier 'this' before the first argument specifies that it's an extension method (in this case to the type 'string'). In a call, the first argument is not 'passed in' because it is already known as the 'calling' object (the object before the dot).
Line 168 ⟶ 176:
The major difference between calling extension methods and calling static helper methods is that static methods are called in [[Polish notation|prefix notation]], whereas extension methods are called in [[infix notation]]. The latter leads to more readable code when the result of one operation is used for another operation.
 
;With static methods: <sourcesyntaxhighlight lang="csharp">HelperClass.Operation2(HelperClass.Operation1(x, arg1), arg2)</sourcesyntaxhighlight>
;With extension methods: <sourcesyntaxhighlight lang="csharp">x.Operation1(arg1).Operation2(arg2)</sourcesyntaxhighlight>
 
==Naming conflicts in extension methods and instance methods==
In C# 3.0, both an instance method and an extension method with the same signature can exist for a class. In such a scenario, the instance method is preferred over the extension method. Neither the compiler nor the [[Microsoft Visual Studio]] IDE warns about the naming conflict. Consider this C# class, where the <code>GetAlphabet()</code> method is invoked on an instance of this class:
 
<sourcesyntaxhighlight lang="csharp">
class AlphabetMaker
{
Line 190 ⟶ 198:
} //method with the same signature.
}
</syntaxhighlight>
</source>
 
Result of invoking <code>GetAlphabet()</code> on an instance of <code>AlphabetMaker</code> if only the extension method exists:
Line 200 ⟶ 208:
==See also==
* [[UFCS]], a way to use free functions as extension methods provided in the [[D programming language]]
* [[typeType classesclass]]es
* [[Anonymous type]]s
* [[Anonymous function|Lambda expressions]]
Line 211 ⟶ 219:
 
== External links ==
*[http://zielonka.codeplex.com/ Open source collection of C# extension methods libraries]. atNow httparchived [https://zielonkaarchive.codeplex.com/?p=zielonka at Codeplex]
*[http://www.codedigest.com/Articles/CSHARP/357_Understanding_Extension_Methods_in_C_.aspx Extension method in C#]
*[httphttps://programmerchoice.blogspot.com/2010/06/extension-methods.html Extension methods]
*[https://csharp-extension.com/ C# Extension Methods]. A collection.
*[http://www.extensionmethod.net/ ExtensionMethod.NET Repository]
*[https://www.extensionmethod.net/ extensionmethod.net Large database with C#, Visual Basic, F# and Javascript extension methods]
*[http://www.a2zmenu.com/CSharp/CSharp-Extension-Method.aspx Explanation and code example]
*[http://blogs.microsoft.co.il/blogs/basil/archive/2008/09/22/defining-your-own-functions-in-jquery.aspx Defining your own functions in jQuery]
*[http://www.drdobbs.com/cpp/uniform-function-call-syntax/232700394 Uniform function call syntax]
*[httphttps://csharp-software-development.blogspot.co.ukcom/2014/09/c-extension-methods.html Extension methods in C#]
*[http://manifold.systems/docs.html#the-extension-manifold Extension Methods in Java with Manifold]
*[https://projectlombok.org/features/experimental/ExtensionMethod Extension Methods in Java with Lombok]
*[https://github.com/rogerkeays/fluent Extension Methods in Java with Fluent]
*[https://kotlinlang.org/docs/reference/extensions.html Extension functions in Kotlin]
 
[[Category:Method (computer programming)]]