Методы расширения позволяют "добавлять" методы в существующие типы без создания нового производного типа, перекомпиляции или иного изменения исходного типа. Методы расширения являются особым видом статического метода, но они вызываются, как если бы они были методами экземпляра в расширенном типе. Для клиентского кода, написанного на языке C#, нет видимого различия между вызовом метода расширения и вызовом методов, фактически определенных в типе. Для того чтоб создать такой метод, нужен статический класс.
Вот пример статического класса, в котором есть метод расширения:
namespace ExtensionMethods
{
static class ExtensionClass
{
/// <summary>
/// метод расширения
/// </summary>
/// <param name="list">
/// коллекцыя продуктов</param>
/// <returns>возвращяет суму
/// цен всех товаров</returns>
public static decimal Get_SumPrise(this List<Product> list)
{
decimal sum = 0;
foreach(Product pr in list)
sum += pr.Price;
return sum;
}
}
По сути дела, это может и запутано, но на самом деле, все очень просто. Здесь ключевое слово this в списке параметров и делает этот метод методом расширения. При вызове этого метода через объектную ссылку не нужно передавать параметров, по сколку this в списке параметров указывает на самого себя.
List<Product> productList = new List<Product>();
productList.Add(new Product("Ноутбук", 600, 505));
А вот собственно и вызов этого метода:
Console.WriteLine("Сума всех цен для продажы: {0}",
productList.Get_SumPrise());
Можно сделать вызов метода, используя полное квалифицированное имя, то есть имя класса и метод, но в этом случае надо передавать параметр!
Вот весь код:
using System;
using System.Collections.Generic;
namespace ExtensionMethods
{
class Program
{
static void Main(string[] args)
{
List<Product> productList = new List<Product>();
productList.Add(new Product("Ноутбук",600,505));
productList.Add(new Product("Музыкальный центр",100,102));
productList.Add(new Product("ДВД",300,225));
productList.Add(new Product("Ноутбук",600,505));
Console.WriteLine("Сума всех цен для продажы: {0}",
productList.Get_SumPrise());
Console.WriteLine("Сума всех закупочных цен: {0}",
productList.Get_SumPurchase_price());
Console.WriteLine("Если все продать,
прибыль будет состовлять: {0}",
productList.Get_Income());
Console.ReadLine();
}
}
}
static class ExtensionClass
{
/// <summary>
/// метод расширения
/// </summary>
/// <param name="list">
/// коллекцыя продуктов</param>
/// <returns>возвращяет суму цен всех товаров</returns>
public static decimal Get_SumPrise(this List<Product> list)
{
decimal sum = 0;
foreach (Product pr in list)
sum += pr.Price;
return sum;
}
/// <summary>
/// метод расширения
/// </summary>
/// <param name="list">коллекцыя продуктов</param>
/// <returns>возвращяет суму закупочных цен всех
/// товаров</returns>
public static decimal Get_SumPurchase_price(
this List<Product> list)
{
decimal sum = 0;
foreach (Product pr in list)
sum += pr.Purchase_price;
return sum;
}
/// <summary>
/// метод расширения
/// </summary>
/// <param name="list">коллекцыя продуктов</param>
/// <returns>прибыль</returns>
public static decimal Get_Income(this List<Product> list)
{
// сума цен для продажы
decimal d1 = list.Get_SumPrise();
//сума закупочных цен
decimal d2 = list.Get_SumPurchase_price();
return d1 - d2; // прибыль, если все продать
}
}
class Product
{
decimal price; // цена для продажы
decimal purchase_price; // закупочная цена
string proudctName; // название продукта
/// <summary>
/// конструктор с параметрами
/// </summary>
/// <param name="proudctName">название продукта</param>
/// <param name="price">цена для продажы</param>
/// <param name="purchase_price">закупочная цена</param>
public Product(string proudctName,
decimal price, decimal purchase_price)
{
this.price = price;
this.purchase_price = purchase_price;
this.proudctName = proudctName;
}
public string ProudctName
{
get { return proudctName; }
set { proudctName = value; }
}
public decimal Price
{
get { return price; }
set { price = value; }
}
public decimal Purchase_price
{
get { return purchase_price; }
set { purchase_price = value; }
}
}

В общем то, как видим, все слишком просто для реализации подобных вещей. Понимаете, что такое поведение можно прикрутить практически к любому графическому контролу.
Если посмотреть что высвечивает intellisense при вызове метода, то увидим что, методы расширения помечены стрелкой в низ:
