0x01 define um delegado, que é equivalente a definir um tipo de variável especial que pode armazenar um método
Abaixo, examinamos o código específico, através do código para entender melhor
delegate void IntMethodInvoker(int x);
Essa linha de código é declarar um delegado, que delegate
é uma palavra-chave, que significa declarar um delegado, void
é o tipo de retorno do método a ser armazenado, IntMethodInvoker
é o nome do tipo de delegado declarado, combinado com a primeira frase, o nome do tipo de variável do livro de classes personalizado int x
É o tipo de retorno do método a ser armazenado
Quais métodos esse representante pode armazenar?
Desde que o tipo de retorno seja o mesmo , os métodos com a mesma lista de parâmetros podem ser armazenados
Neste exemplo, o tipo de retorno é nulo e existe um método do parâmetro int
void test(int t)
{
Console.WriteLine("Just a test" + t )
}
Esse método de teste pode ser armazenado na IntMethodInvoker
instância delegada
O delegado é um tipo especial de objeto. Depois de definir o delegado, você pode criar uma instância e armazenar o método
IntMethodInvoker DelegateTest = test;
Essa linha de código armazenará o endereço do método de teste na IntMethodInvoker
instância delegada DelegateTest
, e o DelegateTest
método de teste poderá ser executado apenas chamando-o no futuro .
DelegateTest(32);
Essa linha de código test(32)
tem o mesmo efeito
Os representantes podem adicionar várias referências de método e os representantes que adicionam várias referências de método são chamados de representantes de difusão seletiva.
Adicione várias referências de método usando + =, para excluir as referências de método adicionadas use- =
0x02 Use delegados para passar métodos como parâmetros
Como dissemos anteriormente que delegação é semelhante à definição de um tipo de variável especial que pode armazenar um método, também podemos usar esse tipo especial como parâmetro formal de um método, adicionar uma referência de método à instância delegada e, em seguida, usar a instância delegada como outra delegada aceite O parâmetro real do método do tipo parâmetro, para obter o efeito de passar o método para outro método
class Program
{
static void Main(string[] args)
{
Test test = new Test();
Test.TestDelegate testDelegate = new Test.TestDelegate(test.Fun);
test.KK(testDelegate);
}
}
class Test
{
public delegate void TestDelegate();
public void Fun()
{
Console.WriteLine("这是一个简单的方法!");
}
public void KK(TestDelegate testDelegate)
{
Console.WriteLine("这是一个接收委托的方法");
testDelegate();
}
}
Este é um exemplo de passagem de um método como parâmetro para outro método
Neste exemplo, primeiro declare uma instância de Teste e, em seguida, declare uma TestDelegate
instância de delegadotestDelegate
testDelegate
test.Fun()
A referência contida no delegado não é chamada no momento test.Fun()
, mas a referência é salva
Próxima execução test.KK(testDelegate)
, quando o testDelegate
delegado for passado para o método KK como um parâmetro formal
Quando o método KK é chamado testDelegate();
, delegue o método Fun
Portanto, o resultado final da execução é
Este é um método para receber um delegado,
é um método simples!
0x03 Func<T>
eAction<T>
Os delegados são muito comuns; portanto, a .Net possui dois tipos de delegados incorporados, para que não tenhamos que declarar o delegado
Action<T>
Delegado genérico significa se referir a um método do tipo de retorno nulo. Existem diferentes variantes desse delegado e métodos que requerem 0 a 16 parâmetros podem ser aceitos
Func<T>
Delegados genéricos são Action<T>
semelhantes, mas se referem a um método que possui um tipo de valor de retorno. Func<T>
O método também pode receber 0 ~ 16 parâmetros, o último padrão é o tipo de retorno, ou seja, Fun<T>
até dezessete parâmetros
Func<string,string,int>
Este Func indica que ele pode receber uma lista de parâmetros como duas strings e retornar um método int.
0x03Lambda e métodos anônimos
Método anônimo:
Func<string, string> anonDel = delegate (string param)
{
param += mid;
param += " and this was added to the string.";
return param;
};
O papel dos métodos anônimos:
Delegados são referências a métodos armazenados, ou seja, para usar um delegado, você deve primeiro ter um método, mas, de fato, muitas vezes a referência de método armazenada no delegado será usada apenas no delegado ou no evento (evento baseado no delegado) É muito problemático definir um método separadamente. No momento, você pode usar o método anônimo. O método acima é anônimo. Vamos olhar para a direita
delegate (string param)
{
param += mid;
param += " and this was added to the string.";
return param;
};
Este é um método anônimo, usando delegate
palavras-chave, se o delegate
substituirmos por um nome comum
KK (string param)
{
param += mid;
param += " and this was added to the string.";
return param;
};
Esse é um método comum (o ponto-e-vírgula no final é o fim da instrução de atribuição de delegação Fun); portanto, o método anônimo é um método comum para remover o nome do método e substituí-lo por um delegado para simplificar o código.
Func<string, string> anonDel =
delegate (string param)
{
param += mid;
param += " and this was added to the string.";
return param;
};
É fácil de entender?
Expressão lambda:
No meu entendimento, as expressões Lambda são na verdade para simplificar métodos anônimos
Ainda usamos o código acima
//匿名方法
delegate (string param)
{
param += mid;
param += " and this was added to the string.";
return param;
}
//Lambda表达式
(string pram) =>
{
param += mid;
param += " and this was added to the string.";
return param;
}
Essas duas versões são equivalentes. => É o operador Lambda. Agora vamos ver quais são os dois lados, a lista de parâmetros à esquerda e o corpo do método à direita.
Este Lambda é realmente um pouco mais complicado, geralmente encontramos o Lambda que será mais simplificado
- Se houver apenas um parâmetro, apenas o nome do parâmetro será suficiente, ou seja, neste Lambda, (carrinho de string) poderá ser reescrito como carrinho de bebê
- Se o corpo do método tiver apenas uma linha de instruções, não serão necessárias chaves e declarações de retorno no bloco de métodos
Por exemplo
Func<double,double> square = (double x) =>
{
return x*x;
};
Essa expressão Lambda pode ser abreviada como
Func<double,double> square = x => x*x
Problema de fechamento de expressão lambda
Aqui está uma sentença, na expressão Lambda usa uma variável externa (não a variável na expressão Lambda), o valor da variável externa é determinado no momento da chamada, não quando a expressão Lambda é definida
int someVal = 5;
Func<int, int> ZZ = x => x + someVal;
someVal = 7;
Console.WriteLine(ZZ(3));
A última saída é 7, porque someVal já é igual a 7 quando o delegado ZZ chama a expressão Lambda