Métodos de extensão (guia de programação translation from VPE for Csharp)
Métodos de extensão permitem que você "Adicionar" métodos para tipos existentes sem criar um novo tipo derivado, recompilar ou modifique de alguma forma o tipo original.sistema autônomo métodos de extensão são um tipo especial de método estático, mas eles são chamados sistema autônomo se fossem métodos de instância no tipo estendido.Para o código de cliente escrito em translation from VPE for Csharp e Visual Basic, não há nenhuma diferença aparente entre chamando um método de extensão e os métodos que, na verdade, são definidos em um tipo.
Os métodos de extensão mais comuns são o LINQ operadores de consulta padrão que adicionam a funcionalidade de consulta para o existente System.Collections.IEnumerable e System.Collections.Generic.IEnumerable<T> tipos. Para usar os operadores de consulta padrão, primeiro colocá-los para o escopo com um using System.Linq diretiva. Em seguida, qualquer tipo que implemente IEnumerable<T> parece ter sistema autônomo métodos de instância GroupBy, OrderBy, Average, e assim por diante. Você pode ver esses métodos adicionais na conclusão da demonstrativo IntelliSense quando você digitar "ponto" após uma instância de umIEnumerable<T> Digite sistema autônomo List<T> ou Array.
O exemplo a seguir mostra como chamar o operador de consulta padrão OrderBy método em uma matriz de inteiros. A expressão entre parênteses é uma expressão lambda.Muitos operadores de consulta padrão levar sistema autônomo expressões lambda sistema autônomo parâmetros, mas isso não é um requisito para sistema autônomo métodos de extensão.Para obter mais informações, consulte Expressões lambda (guia de programação translation from VPE for Csharp).
class ExtensionMethods2
{
static void Main()
{
int[] ints = { 10, 45, 15, 39, 21, 26 };
var result = ints.OrderBy(g => g);
foreach (var i in result)
{
System.Console.Write(i + " ");
}
}
}
//Output: 10 15 21 26 39 45
Métodos de extensão são definidos sistema autônomo métodos estático, mas são chamados usando a sintaxe do método de instância.Seu primeiro parâmetro especifica qual tipo o método opera em e o parâmetro é precedido pela Issomodificador de .Os métodos de extensão são somente no escopo quando você importa explicitamente o namespace para o código-fonte com um using diretiva.
O exemplo a seguir mostra um método de extensão definido para o System.String classe. Observe que ela é definida dentro de um não aninhado não-genéricas estático classe:
namespace ExtensionMethods
{
public static class MyExtensions
{
public static int WordCount(this String str)
{
return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length;
}
}
}
The WordCount método de extensão pode ser transferido para o escopo com isso using diretiva:
using ExtensionMethods;
E ele pode ser chamado de um aplicativo usando esta sintaxe:
string s = "Hello Extension Methods";
int i = s.WordCount();
Em seu código você chamar o método de extensão com sintaxe do método de instância.No entanto, a linguagem intermediária (IL) gerada pelo compilador converte seu código em uma telefonar de método estático.Portanto, o princípio de encapsulamento não é realmente sendo violado.Na verdade, os métodos de extensão não é possível acessar variáveis particulares no tipo que eles estão estendendo.
Para obter mais informações, consulte Como: Implementar e telefonar um método de extensão personalizada (guia de programação translation from VPE for Csharp).
Em geral, você será provavelmente chamado métodos de extensão com muito mais freqüência do que implementar seus próprios.Porque os métodos de extensão são chamados usando a sintaxe do método de instância, não é necessário nenhum conhecimento especial para utilizá-las a partir do código do cliente.Para habilitar métodos de extensão para um determinado tipo, adicione apenas um using diretiva para o namespace em que os métodos são definidos. Por exemplo, para usar os operadores de consulta padrão, adicione este using diretiva para seu código:
using System.Linq;
(Talvez seja necessário adicionar uma referência a sistema.Core.dll.) Você observará que sistema autônomo operadores de consulta padrão exibido no IntelliSense sistema autônomo métodos adicionais disponível para a maioria dos IEnumerable<T> tipos.
Observação: |
---|
Embora operadores de consulta padrão não aparecem no IntelliSense Para String, elas ainda estarem disponível. |
Métodos de extensão na ligação time de compilar
Você pode usar os métodos de extensão para estender uma classe ou interface, mas não para substituí-los.Um método de extensão com o mesmo nome e assinatura sistema autônomo uma interface ou método da classe nunca será chamado.No momento da compilar, os métodos de extensão sempre têm prioridade mais baixa do que os métodos de instância definida no próprio tipo.Em outras palavras, se um tipo tem um método chamado Process(int i)e você tem um método de extensão com a mesma assinatura, o compilador sempre irá BIND para o método de instância. Quando o compilador encontra uma invocação de método, ele primeiro procura de uma correspondência nos métodos de instância do tipo.Se nenhuma correspondência for encontrada, ele irá procurar por quaisquer métodos de extensão que são definidos para o tipo e BIND o primeiro método de extensão que encontrar.O exemplo a seguir demonstra como o compilador determina qual método de extensão ou o método de instância para BIND a.
Exemplo
O exemplo a seguir demonstra as regras que segue o compilador translation from VPE for Csharp determinar se deseja BIND uma telefonar de método para um método de instância no tipo ou a um método de extensão.O estático classe Extensions contém definidos para qualquer tipo que implementa os métodos de extensão IMyInterface. Classes A, B, e C todas as implementam a interface.
The MethodB método nunca é chamado porque seu nome e assinatura correspondem exatamente métodos já implementados pelas classes.
Quando o compilador não pode localizar um método de instância com uma assinatura correspondente, ele irá acoplar a um método de extensão correspondente se existir um.
namespace Extensions
{
using System;
using ExtensionMethodsDemo1;
// Define extension methods for any type that implements IMyInterface.
public static class Extension
{
public static void MethodA(this IMyInterface myInterface, int i)
{
Console.WriteLine("Extension.MethodA(this IMyInterface myInterface, int i)");
}
public static void MethodA(this IMyInterface myInterface, string s)
{
Console.WriteLine("Extension.MethodA(this IMyInterface myInterface, string s)");
}
// This method is never called, because the three classes implement MethodB.
public static void MethodB(this IMyInterface myInterface)
{
Console.WriteLine("Extension.MethodB(this IMyInterface myInterface)");
}
}
}
namespace ExtensionMethodsDemo1
{
using System;
using Extensions;
public interface IMyInterface
{
void MethodB();
}
class A : IMyInterface
{
public void MethodB(){Console.WriteLine("A.MethodB()");}
}
class B : IMyInterface
{
public void MethodB() { Console.WriteLine("B.MethodB()"); }
public void MethodA(int i) { Console.WriteLine("B.MethodA(int i)"); }
}
class C : IMyInterface
{
public void MethodB() { Console.WriteLine("C.MethodB()"); }
public void MethodA(object obj) { Console.WriteLine("C.MethodA(object obj)"); }
}
class ExtMethodDemo
{
static void Main(string[] args)
{
A a = new A();
B b = new B();
C c = new C();
TestMethodBinding(a,b,c);
}
static void TestMethodBinding(A a, B b, C c)
{
// A has no methods, so each call resolves to
// the extension methods whose signatures match.
a.MethodA(1); // Extension.MethodA(object, int)
a.MethodA("hello"); // Extension.MethodA(object, string)
a.MethodB(); // A.MethodB()
// B itself has a method with this signature.
b.MethodA(1); // B.MethodA(int)
b.MethodB(); // B.MethodB()
// B has no matching method, but Extension does.
b.MethodA("hello"); // Extension.MethodA(object, string)
// In each case C has a matching instance method.
c.MethodA(1); // C.MethodA(object)
c.MethodA("hello"); // C.MethodA(object)
c.MethodB(); // C.MethodB()
}
}
}
/* Output:
Extension.MethodA(this IMyInterface myInterface, int i)
Extension.MethodA(this IMyInterface myInterface, string s)
A.MethodB()
B.MethodA(int i)
B.MethodB()
Extension.MethodA(this IMyInterface myInterface, string s)
C.MethodA(object obj)
C.MethodA(object obj)
C.MethodB()
*/
Diretrizes gerais
Em geral, é recomendável que você implemente métodos de extensão com moderação e somente quando necessário.Sempre que possível, código de cliente que deve estender um tipo existente deve fazê-lo criando um novo tipo derivado do tipo existente.Para obter mais informações, consulte Herança (Guia de programação C#).
Ao usar um método de extensão para estender um tipo cujo código fonte não é possível alterar, você corre o risco que uma alteração na implementação do tipo fará com que seu método de extensão quebrar.
Se você implementar métodos de extensão para um determinado tipo, lembre-se os dois pontos seguintes:
Um método de extensão nunca será chamado se ele tiver a mesma assinatura de um método definido no tipo.
Métodos de extensão são trazidos para o escopo no nível do espaço para nome.Por exemplo, se você tiver várias classes estáticas que contêm métodos de extensão em um único namespace chamado Extensions, eles serão todos sejam trazidos para escopo pela using Extensions; diretiva.
Implementadores de bibliotecas de classe não devem usar os métodos de extensão para evitar a criação de novas versões de módulos (assemblies).Se você deseja adicionar nova funcionalidade significativa para uma biblioteca, e você possui o código-fonte, você deve seguir as diretrizes do .NET estrutura padrão para o controle de versão do assembly.Para obter mais informações, consulte Versionamento de Assembly.
Consulte também
Conceitos
Visão geral sobre operadores de consulta padrão
Referência
Expressões lambda (guia de programação translation from VPE for Csharp)
Outros recursos
Conversão de regras por exemplo parâmetros e seu impacto