Extension method

In object-oriented computer programming, an extension method is a method added to an object after the original object was 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.[1]

Not all languages implement extension methods in an equally safe manner, however. For instance, languages such as C#, Java (via Manifold, Lombok, or Fluent), and Kotlin don't alter the extended class in any way, because doing so may break class hierarchies and interfere with virtual method dispatching. Instead, these languages strictly implement extension methods statically and use static dispatching to invoke them.

Support in programming languages

Extension methods are features of numerous languages including C#, Java via Manifold or Lombok or Fluent, Gosu, JavaScript, Oxygene, Ruby, Smalltalk, Kotlin, Dart, Visual Basic.NET, and Xojo. In dynamic languages like 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-patching", employed in libraries such as gevent).

In VB.NET and Oxygene, they are recognized by the presence of the "extension" keyword or attribute. In Xojo, the "Extends" keyword is used with global methods.

In C#, they are implemented as static methods in static classes, with the first argument being of extended class and preceded by "this" keyword.

In Java, extension methods are added via Manifold, a jar file added to the project's classpath. Similar to C#, a Java extension method is declared static in an @Extension class where the first argument has the same type as the extended class and is annotated with @This. Alternatively, the 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 methodsFor:) 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 *etoys* 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 class keyword 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 Refinements, but it is known to be less used.

In Swift, the extension 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.[2]

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 query syntax which for the moment is unique to the primary Microsoft .NET languages.

Console.WriteLine(new[] { Math.PI, Math.E }.Where(d => d > 3).Select(d => Math.Sin(d / 2)).Sum());
// Output:
// 1

Centralize common behavior

However, extension methods allow features to be implemented once in ways that enable reuse without the need for inheritance or the overhead of virtual method invocations, or to require implementors of an interface to implement either trivial or woefully complex functionality.

A particularly useful scenario is if the feature operates on an interface for which there is no concrete implementation or a useful implementation is not provided by the class library author, e.g. such as is often the case in libraries that provide developers a plugin architecture or similar functionality.

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.

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)
    {
        if (logger != null)
            logger.Write(string.Format(format, args));
    }
}
  • use as :
    var logger = new MyLoggerImplementation();
    logger.Write("{0}: {1}", "kiddo sais", "Mam mam mam mam ...");
    logger.Write("{0}: {1}", "kiddo sais", "Ma ma ma ma... ");
    logger.Write("{0}: {1}", "kiddo sais", "Mama mama mama mama ");
    logger.Write("{0}: {1}", "kiddo sais", "Mamma mamma mamma ... ");
    logger.Write("{0}: {1}", "kiddo sais", "Elisabeth Lizzy Liz...");
    logger.Write("{0}: {1}", "mamma sais", "WHAT?!?!!!");
    logger.Write("{0}: {1}", "kiddo sais", "hi.");
    

Better loose coupling

Extension methods allow users of class libraries to refrain from ever declaring an argument, variable, or anything else with a type that comes from that library. Construction and conversion of the types used in the class library can be implemented as extension methods. After carefully implementing the conversions and factories, switching from one class library to another can be made as easy as changing the using statement that makes the extension methods available for the compiler to bind to.

Fluent application programmer's interfaces

Extension methods have special use in implementing so called fluent interfaces. An example is Microsoft's Entity Framework configuration API, which allows for example to write code that resembles regular English as closely as practical.

One could argue this is just as well possible without extension methods, but one will find that in practice, extension methods provide a superior experience because less constraints are placed on the class hierarchy to make it work - and read - as desired.

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".

public class TodoItemContext : DbContext 
{
    public DbSet<TodoItem> TodoItems { get; set; }
    public DbSet<TodoList> TodoLists { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<TodoList>()
                    .HasKey(e => e.TodoListId)
                    .HasEntitySetName("Lists")
                    .HasMany(e => e.Todos)
                    .WithRequired(e => e.TodoList);
    }
}

Productivity

Consider for example IEnumerable and note its simplicity - there is just one method, yet it is the basis of LINQ more or less. There are many implementations 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 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.

public class BankAccount : IEnumerable<decimal> 
{
    private List<Tuple<DateTime, decimal>> credits; // assumed all negative
    private List<Tuple<DateTime, decimal>> debits; // assumed all positive

    public IEnumerator<decimal> GetEnumerator() 
    {
        var query = from dc in debits.Union(credits) 
                    orderby dc.Item1 /* Date */ 
                    select dc.Item2; /* Amount */
    
        foreach (var amount in query)
            yield return amount;
    }
}
// given an instance of BankAccount called ba and a using System.Linq on top of the current file,
// 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

Performance

That said, additional implementations of a feature provided by an extension method can be added to improve performance, or to deal with differently implemented interface implementations, such as providing the compiler an implementation of IEnumerable specifically for arrays (in System.SZArrayHelper), which it will automatically choose for extension method calls on array typed references, since their argument will be more specific (this T[] value) than the extension method with the same name that operates on instances of the IEnumerable interface (this IEnumerable value).

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 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.

The problem

In programming, situations arise where it is necessary to add functionality to an existing class—for instance by adding a new method. Normally the programmer would modify the existing class's source code, but this forces the programmer to recompile all binaries with these new changes and requires that the programmer be able to modify the class, which is not always possible, for example when using classes from a third-party assembly. This is typically worked around in one of three ways, all of which are somewhat limited and unintuitive [citation needed]:

  1. Inherit the class and then implement the functionality in an instance method in the derived class.
  2. Implement the functionality in a static method added to a helper class.
  3. Use aggregation instead of inheritance.

Current C# solutions

The first option is in principle easier, but it is unfortunately limited by the fact that many classes restrict inheritance of certain members or forbid it completely. This includes sealed class and the different primitive data types in C# such as int, float and string. The second option, on the other hand, does not share these restrictions, but it may be less intuitive as it requires a reference to a separate class instead of using the methods of the class in question directly.

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:

string x = "some string value";
string y = Utility.Reverse(x);

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:

string x = "some string value";
string y = x.Reverse();

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;

Dim x As String = "some string value"
x.Reverse()

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.

Extension methods

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.

public static class Utility
{
    public static string Reverse(this string input)
    {
        char[] chars = input.ToCharArray();
        Array.Reverse(chars);
        return new String(chars);
    }
}

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).

The major difference between calling extension methods and calling static helper methods is that static methods are called in 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
HelperClass.Operation2(HelperClass.Operation1(x, arg1), arg2)
With extension methods
x.Operation1(arg1).Operation2(arg2)

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 GetAlphabet() method is invoked on an instance of this class:

class AlphabetMaker 
{
    public void GetAlphabet()       
    {                               //When this method is implemented,
        Console.WriteLine("abc");   //it will shadow the implementation
    }                               //in the ExtensionMethods class.
}

static class ExtensionMethods
{
    public static void GetAlphabet(this AlphabetMaker am)   
    {                               //This will only be called                       
        Console.WriteLine("ABC");   //if there is no instance
    }                               //method with the same signature.   
}

Result of invoking GetAlphabet() on an instance of AlphabetMaker if only the extension method exists:

ABC

Result if both the instance method and the extension method exist:

abc

See also

References

  1. ^ "Extension Methods". Microsoft. Retrieved 2008-11-23.
  2. ^ "Extensions — The Swift Programming Language (Swift 5.7)". docs.swift.org. Retrieved 2022-06-12.

Read other articles:

Bagian dari seriGereja Katolik menurut negara Afrika Afrika Selatan Afrika Tengah Aljazair Angola Benin Botswana Burkina Faso Burundi Chad Eritrea Eswatini Etiopia Gabon Gambia Ghana Guinea Guinea-Bissau Guinea Khatulistiwa Jibuti Kamerun Kenya Komoro Lesotho Liberia Libya Madagaskar Malawi Mali Maroko Mauritania Mauritius Mesir Mozambik Namibia Niger Nigeria Pantai Gading Republik Demokratik Kongo Republik Kongo Rwanda Sao Tome dan Principe Senegal Seychelles Sierra Leone Somalia Somaliland ...

 

Taking care of one's own health This article is about the maintenance of one's personal well-being and health. For a person's assessment of their own value and dignity, see Self-esteem. Self-careWalking is beneficial for the maintenance of good health.MeSHD012648[edit on Wikidata] Self-care has been defined as the process of establishing behaviors to ensure holistic well-being of oneself, to promote health, and actively manage illness when it occurs.[1] Individuals engage in some ...

 

يفتقر محتوى هذه المقالة إلى الاستشهاد بمصادر. فضلاً، ساهم في تطوير هذه المقالة من خلال إضافة مصادر موثوق بها. أي معلومات غير موثقة يمكن التشكيك بها وإزالتها. (ديسمبر 2018) هذه المقالة يتيمة إذ تصل إليها مقالات أخرى قليلة جدًا. فضلًا، ساعد بإضافة وصلة إليها في مقالات متعلقة بها...

العلاقات السودانية الكرواتية السودان كرواتيا   السودان   كرواتيا تعديل مصدري - تعديل   العلاقات السودانية الكرواتية هي العلاقات الثنائية التي تجمع بين السودان وكرواتيا.[1][2][3][4][5] مقارنة بين البلدين هذه مقارنة عامة ومرجعية للدولتين: وجه ال...

 

Bulgarian anti-Jewish law (1941–1944) Part of a series onDiscrimination Forms Institutional Structural Attributes Age Caste Class Dialect Disability Genetic Hair texture Height Language Looks Mental disorder Race / Ethnicity Skin color Scientific racism Rank Sex Sexual orientation Species Size Viewpoint Social Arophobia Acephobia Adultism Anti-albinism Anti-autism Anti-homelessness Anti-drug addicts Anti-intellectualism Anti-intersex Anti-left handedness Anti-Masonry Antisemitism A...

 

Peta infrastruktur dan tata guna lahan di Komune Bourron-Marlotte.  = Kawasan perkotaan  = Lahan subur  = Padang rumput  = Lahan pertanaman campuran  = Hutan  = Vegetasi perdu  = Lahan basah  = Anak sungaiBourron-MarlotteNegaraPrancisArondisemenFontainebleauKantonNemoursPemerintahan • Wali kota (2008-2014) Juliette Vilgrain • Populasi12.737Kode INSEE/pos77048 / 2 Population sans doubles comptes: penghitungan tunggal penduduk...

American college basketball season 2011–12 Kansas Jayhawks men's basketballBig 12 regular season championsNCAA tournament Runner-upConferenceBig 12RankingCoachesNo. 2APNo. 6Record32–7 (16–2 Big 12)Head coachBill Self (9th Season)Assistant coaches Joe Dooley (9th season) Danny Manning (5th season) Kurtis Townsend (8th season) Captains Thomas Robinson Tyshawn Taylor Home arenaAllen FieldhouseSeasons← 2010–112012–13 → 2011–12 Big 12 men's bas...

 

Season of television series Inazuma Eleven: AresKey visualNo. of episodes26ReleaseOriginal networkTXN (TV Tokyo, TV Osaka)Original releaseApril 6 (2018-04-06) –September 28, 2018 (2018-09-28)Season chronology← PreviousGO: Galaxy Next →Orion no Kokuin Inazuma Eleven: Ares[1] (イナズマイレブン アレスの天秤, Inazuma Irebun Aresu no Tenbin, lit. Inazuma Eleven: Scale of Ares) is a 2018 Japanese television anime television series produced by OLM...

 

Medical conditionLobo's diseaseOther namesLobo disease,[1] Jorge Lobo's disease,[2] Lacaziosis,[3] keloidal blastomycosis[4]Histopathological changes in the skin seen in lobomycosis. Source: CDCSpecialtyInfectious diseases CausesLacazia loboi[1] Lobomycosis is a fungal infection of the skin.[4] It usually presents with bumps in the skin, firm swellings, deep skin lesions, or malignant tumors.[1] It is caused by Lacazia loboi (former...

Biviofrazione Bivio – VedutaBivio con la vista di Piz Lagrev, Piz Julier e la strada del passo del Giulio LocalizzazioneStato Svizzera Cantone Grigioni RegioneAlbula ComuneSurses TerritorioCoordinate46°28′12″N 9°39′05″E / 46.47°N 9.651389°E46.47; 9.651389 (Bivio)Coordinate: 46°28′12″N 9°39′05″E / 46.47°N 9.651389°E46.47; 9.651389 (Bivio) Altitudine1 769 m s.l.m. Superficie76,73 km² Abitanti189 (2014) ...

 

Gugus bola Messier 92 yang terdapat di rasi Herkules. Gugus bintang atau Awan bintang merupakan kelompok bintang yang secara gravitasi dan awal pembentukannya terikat satu sama lain. Ada dua jenis gugus bintang yang umum ditemukan, yaitu: Gugus bola merupakan kelompok ratusan atau ribuan bintang yang berusia sangat tua dan terikat gravitasi erat satu sama lain. Karena jarak antar bintangnya yang relatif dekat, gugus ini membentuk seperti bola dimana kepadatan bintang semakin tinggi di bagian ...

 

For other uses, see Morioka (disambiguation). You can help expand this article with text translated from the corresponding article in Japanese. (September 2018) Click [show] for important translation instructions. Machine translation, like DeepL or Google Translate, is a useful starting point for translations, but translators must revise errors as necessary and confirm that the translation is accurate, rather than simply copy-pasting machine-translated text into the English Wikipedia. Co...

His Britannic Majesty’s Ambassadorto the United States of AmericaRoyal Arms of His Majesty's GovernmentIncumbentDame Karen Piercesince 23 March 2020[1]Foreign and Commonwealth Office British Embassy, Washington D.C.StyleHer Excellency Madam AmbassadorReports toSecretary of State for Foreign and Commonwealth AffairsResidenceBritish Ambassador's Residence, Washington, D.C.AppointerThe King on advice of the Prime Minister of the United KingdomTerm lengthAt His Majesty's pleasureI...

 

WWI British infantry division 16th (Irish) DivisionActive1914 – 1919Country United Kingdom of Great Britain and IrelandBranch British ArmyTypeInfantrySizeDivisionEngagements World War I Battle of Hulluch Battle of the Somme Battle of Guillemont Battle of Ginchy Battle of Messines Battle of Passchendaele German spring offensive CommandersNotablecommandersMajor-General William HickieMilitary unit The 16th (Irish) Division was an infantry division of the British Army, raised for serv...

 

2020年夏季残疾人奥林匹克运动会中国香港代表團香港特别行政区区旗IPC編碼HKGNPC香港殘疾人奧委會暨傷殘人士體育協會網站www.paralympic.hk(英文)(繁體中文)2020年夏季残疾人奥林匹克运动会(東京)2021年8月24日至9月5日(受2019冠状病毒病疫情影响推迟,但仍保留原定名称)運動員24參賽項目8个大项旗手任國芬、許家俊(開幕式) 朱文佳(閉幕式)獎牌榜排名第68 金牌 銀...

  لمعانٍ أخرى، طالع أوغدن (توضيح). أوغدن     الإحداثيات 40°06′49″N 87°57′26″W / 40.1136°N 87.9572°W / 40.1136; -87.9572   [1] تاريخ التأسيس 1870  تقسيم إداري  البلد الولايات المتحدة[2]  التقسيم الأعلى مقاطعة شامبين  خصائص جغرافية  المساحة 0.58 ميل مربع  ا�...

 

American-bred champion Thoroughbred racehorse RuffianSireReviewerGrandsireBold RulerDamShenanigansDamsireNative DancerSexFillyFoaledApril 17, 1972Paris, Kentucky, U.S.DiedJuly 7, 1975(1975-07-07) (aged 3)Elmont, New York, U.S.CountryUnited StatesColourDark bayBreederStuart & Barbara JanneyOwnerStuart & Barbara JanneyTrainerFrank Y. Whiteley Jr.Record11: 10-0-0 (1 DNF)Earnings$313,428[1]Major winsFashion Stakes (1974)Astoria Stakes (1974)Spinaway Stakes (1974)Sorority Stak...

 

Дмитриевский собор (Владимир), построенный в 1197 году Годы 1193 · 1194 · 1195 · 1196 — 1197 — 1198 · 1199 · 1200 · 1201 Десятилетия 1170-е · 1180-е — 1190-е — 1200-е · 1210-е Века XI век — XII век — XIII век 2-е тысячелетие X век XI век XII век XIII век XIV век 1090-е 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100-е 1...

العلاقات السنغالية الشمال مقدونية السنغال شمال مقدونيا   السنغال   شمال مقدونيا تعديل مصدري - تعديل   العلاقات السنغالية الشمال مقدونية هي العلاقات الثنائية التي تجمع بين السنغال وشمال مقدونيا.[1][2][3][4][5] مقارنة بين البلدين هذه مقارنة عامة...

 

Neighbourhood in Ottawa, Ontario, CanadaHeron GateNeighbourhoodSandalwood ParkHeron GateLocation within OttawaCoordinates: 45°22′40″N 75°39′00″W / 45.37778°N 75.65000°W / 45.37778; -75.65000CountryCanadaProvinceOntarioCityOttawaGovernment • MPsDavid McGuinty • MPPsJohn Fraser • CouncillorsMarty Carr, Jessica Bradley • Community associationHerongate Tenant CoalitionArea • Total1.538 km2 (0.594...