Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharpNotesForProfessionals.pdf
Скачиваний:
57
Добавлен:
20.05.2023
Размер:
6.12 Mб
Скачать

View Demo

Section 48.5: Extension methods can only see public (or internal) members of the extended class

public class SomeClass

{

public void DoStuff()

{

}

protected void DoMagic()

{

}

}

public static class SomeClassExtensions

{

public static void DoStuffWrapper(this SomeClass someInstance)

{

someInstance.DoStuff(); // ok

}

public static void DoMagicWrapper(this SomeClass someInstance)

{

someInstance.DoMagic(); // compilation error

}

}

Extension methods are just a syntactic sugar, and are not actually members of the class they extend. This means that they cannot break encapsulation—they only have access to public (or when implemented in the same assembly, internal) fields, properties and methods.

Section 48.6: Extension methods for chaining

When an extension method returns a value that has the same type as its this argument, it can be used to "chain" one or more method calls with a compatible signature. This can be useful for sealed and/or primitive types, and allows the creation of so-called "fluent" APIs if the method names read like natural human language.

void Main()

{

int result = 5.Increment().Decrement().Increment();

// result is now 6

}

public static class IntExtensions

{

public static int Increment(this int number) { return ++number;

}

public static int Decrement(this int number) { return --number;

}

}

GoalKicker.com – C# Notes for Professionals

199

Or like this

void Main()

{

int[] ints = new[] { 1, 2, 3, 4, 5, 6}; int[] a = ints.WhereEven();

//a is { 2, 4, 6 };

int[] b = ints.WhereEven().WhereGreaterThan(2);

//b is { 4, 6 };

}

public static class IntArrayExtensions

{

public static int[] WhereEven(this int[] array)

{

//Enumerable.* extension methods use a fluent approach return array.Where(i => (i%2) == 0).ToArray();

}

public static int[] WhereGreaterThan(this int[] array, int value)

{

return array.Where(i => i > value).ToArray();

}

}

Section 48.7: Extension methods with Enumeration

Extension methods are useful for adding functionality to enumerations.

One common use is to implement a conversion method.

public enum YesNo

{

Yes,

No,

}

public static class EnumExtentions

{

public static bool ToBool(this YesNo yn)

{

return yn == YesNo.Yes;

}

public static YesNo ToYesNo(this bool yn)

{

return yn ? YesNo.Yes : YesNo.No;

}

}

Now you can quickly convert your enum value to a di erent type. In this case a bool.

bool yesNoBool = YesNo.Yes.ToBool();

//

yesNoBool

==

true

YesNo yesNoEnum = false.ToYesNo();

//

yesNoEnum

==

YesNo.No

 

 

 

 

 

Alternatively extension methods can be used to add property like methods.

public enum Element

{

Hydrogen,

GoalKicker.com – C# Notes for Professionals

200

Helium,

Lithium,

Beryllium,

Boron,

Carbon,

Nitrogen, Oxygen

//Etc

}

public static class ElementExtensions

{

public static double AtomicMass(this Element element)

{

switch(element)

{

case Element.Hydrogen: return 1.00794; case Element.Helium: return 4.002602; case Element.Lithium: return 6.941; case Element.Beryllium: return 9.012182; case Element.Boron: return 10.811; case Element.Carbon: return 12.0107; case Element.Nitrogen: return 14.0067; case Element.Oxygen: return 15.9994;

//Etc

}

return double.Nan;

}

}

var massWater = 2*Element.Hydrogen.AtomicMass() + Element.Oxygen.AtomicMass();

Section 48.8: Extension methods dispatch based on static type

The static (compile-time) type is used rather than the dynamic (run-time type) to match parameters.

public class Base

{

public virtual string GetName()

{

return "Base";

}

}

public class Derived : Base

{

public override string GetName()

{

return "Derived";

}

}

public static class Extensions

{

public static string GetNameByExtension(this Base item)

{

return "Base";

}

public static string GetNameByExtension(this Derived item)

GoalKicker.com – C# Notes for Professionals

201

{

return "Derived";

}

}

public static class Program

{

public static void Main()

{

Derived derived = new Derived(); Base @base = derived;

// Use the instance method "GetName"

Console.WriteLine(derived.GetName()); // Prints "Derived" Console.WriteLine(@base.GetName()); // Prints "Derived"

// Use the static extension method "GetNameByExtension"

Console.WriteLine(derived.GetNameByExtension()); // Prints "Derived" Console.WriteLine(@base.GetNameByExtension()); // Prints "Base"

}

}

Live Demo on .NET Fiddle

Also the dispatch based on static type does not allow an extension method to be called on a dynamic object:

public class Person

{

public string Name { get; set; }

}

public static class ExtenionPerson

{

public static string GetPersonName(this Person person)

{

return person.Name;

}

}

dynamic person = new Person { Name = "Jon" };

var name = person.GetPersonName(); // RuntimeBinderException is thrown

Section 48.9: Extension methods on Interfaces

One useful feature of extension methods is that you can create common methods for an interface. Normally an interface cannot have shared implementations, but with extension methods they can.

public interface IVehicle

{

int MilesDriven { get; set; }

}

public static class Extensions

{

public static int FeetDriven(this IVehicle vehicle)

{

return vehicle.MilesDriven * 5028;

}

}

GoalKicker.com – C# Notes for Professionals

202