Eu aprendi recentemente que você pode criar algum método com parâmetros ilimitados, por exemplo:
SomeMethod(params int[] numbers);
mas minha pergunta é: qual é a diferença entre isso e apenas criar um método que recebe uma lista ou uma matriz?
SomeMethod(int[] numbers);
SomeMethod(List<int> numbers);
talvez tenha algum impacto no desempenho? Não entendo completamente nem vejo de que maneira você preferiria aquele com parâmetros ilimitados.
Uma pesquisa rápida no google não ajudou, espero que você possa me ajudar.
params
também requer que o tipo do argumento seja uma matriz. Se você precisar consumir uma coleção que não seja uma matriz, pode fazer mais sentido fornecer um nãoparams
argumento.Console.Write
.Respostas:
A diferença entre
e
é que M pode ser chamado assim:
ou assim:
mas N só pode ser chamado da segunda maneira, não da primeira .
O impacto no desempenho é que, se você liga
M
pela primeira ou pela segunda maneira, de qualquer maneira você cria uma matriz. A criação de uma matriz afeta o desempenho, pois leva tempo e memória. Lembre-se de que os impactos no desempenho devem ser medidos em relação às metas de desempenho; é improvável que o custo de criação de uma matriz extra seja o fator determinante que é a diferença entre sucesso e fracasso no mercado.É pura e inteiramente uma conveniência para o autor do código que está chamando o método; é simplesmente mais curto e fácil de escrever
em vez de escrever
Apenas salva algumas teclas pressionadas no lado do chamador. Isso é tudo.
Algumas perguntas que você não fez, mas talvez queira saber a resposta para:
Os métodos que permitem que um número variável de argumentos sejam passados no lado do chamador são chamados variadic . Os métodos de parâmetros são como o C # implementa métodos variados.
Quando confrontado com um problema de resolução de sobrecarga, o C # considerará os formulários "normal" e "expandido", e o formulário "normal" sempre vence se ambos forem aplicáveis. Por exemplo, considere isso:
e nós temos uma ligação
Existem duas possibilidades aplicáveis. No formato "normal", chamamos
P
e passamos uma referência nula para a matriz. Na forma "expandida", chamamosP(new object[] { null })
. Nesse caso, a forma normal vence. Se recebemos uma chamadaP(null, null)
, o formulário normal é inaplicável e o formulário expandido vence por padrão.Desafio : suponha que tenhamos
var s = new[] { "hello" };
uma ligaçãoP(s);
. Descreva o que acontece no site da chamada e por quê. Você pode se surpreender!Desafio : Suponha que temos ambos
void P(object x){}
evoid P(params object[] x){}
. O queP(null)
faz e por quê?Desafio : Suponha que temos ambos
void M(string x){}
evoid M(params string[] x){}
. O queM(null)
faz e por quê? Como isso difere do caso anterior?fonte
P(null)
vs.P((object)null)
vs.P((object[])null)
- onde posso encontrar uma explicação para essa diferença? Parece quenull
teve algum tipo especial , que se converte em matriz em vez de objeto (P(null)
), mas considera a conversão em sequência ou matriz de seqüências ambíguas (M(null)
) ... que parece muito estranha, seria de esperar ambígua nos dois casos ou escolher a versão de argumento único (o que não existe). Mas acho que é mais sobreparams
ser de alguma forma genérico , como referência universal (&&
) nos modelos C ++ e, portanto, uma melhor correspondência (no Ch2, não no Ch3).object[]
sãoobject
, mas nem todosobject
sãoobject[]
, portanto,object[]
é mais específico.string[]
sãostring
". De fato, NOstring[]
sãostring
e NÃOstring
sãostring[]
, portanto,string
não é mais específico ou mais geral questring[]
, e obtemos um erro de ambiguidade quando solicitados a escolher.object[]
sãoobject
...object[]
é mais específico, entãoP(null)
vale para a matriz mais específica, thx, era isso que eu estava perdendo. Encontrei algumas regras aqui: docs.microsoft.com/en-us/dotnet/csharp/language-reference/…Só fiz um pequeno protótipo. A resposta parece ser
params
simplesmente açúcar sintático para passar em uma matriz. Isso não é realmente uma surpresa. Criei duas versões do mesmo método, onde a única diferença é a palavra-chave "params". A IL gerada para ambos era idêntica, exceto que aSystem.ParamArrayAttribute
foi aplicada àparams
versão.Além disso, a IL gerada no site da chamada também foi a mesma entre eu chamar o método com um declarado manualmente
new int[]
e chamar o método apenas usando osparams
argumentos.Então, a resposta parece ser "conveniência". Não parece haver nenhuma diferença no desempenho. Você também pode chamar uma
params
função com uma matriz, o que também não é muito surpreendente. Tudo se resume a se é mais fácil para o consumidor do seu método chamá-lo com qualquer número de parâmetros (por exemplosomeMethod(1, 2, 3)
) do que sempre ter que criar uma coleção primeiro (por exemplosomeMethod(new List<int>() { 1, 2, 3 } )
).fonte
O recurso de parâmetros ilimitados oferece os seguintes benefícios em muitos cenários:
Aqui está um exemplo em que a opção de parâmetros ilimitados é uma ótima opção
Considere que um aplicativo para enviar e-mails precisa ser criado.
A função que envia o email deve poder manipular valores únicos ou múltiplos para os campos 'Para', 'CC' e 'BCC'.
Se os tipos de parâmetros forem fixos em matrizes ou listas para todos os campos (Para, CC, BCC), a função de chamada será forçada a lidar com toda a complexidade da definição de 3 matrizes ou listas para chamar a função de remetente de email .
Mesmo que o chamador deseje enviar um email para apenas um endereço, a função remetente do email forçará o chamador a definir e enviar 3 matrizes diferentes como parâmetros.
Se a função de remetente de email adotar a abordagem de parâmetros ilimitados, a função de chamada não precisará lidar com toda a complexidade.
A abordagem de parâmetros ilimitados contribui para melhorar o desempenho do aplicativo em tempo de execução, evitando a criação de matrizes ou listas sempre que desnecessário.
fonte
De uma perspectiva de estilo sem desempenho , a
params
palavra-chave é realmente boa quando você deseja enviar uma lista opcional de parâmetros.Pessoalmente, eu usaria
params
quando meu código fosse algo comoA parte boa disso é que eu posso usar esse método em todo o lugar sem precisar criar uma matriz ou lista todas as vezes.
Eu usaria
array
oulist
quando sei que sempre transmitirei a essa função um conjunto de dados que já estão reunidos comoEu vejo o benefício da
params
flexibilidade que ele adiciona. Pode ser um impacto relativamente pequeno no seu código, mas ainda é uma boa ferramenta.fonte
A convenção de chamada é diferente. Por exemplo ...
No primeiro caso, você pode passar tantas entradas quanto parâmetros separados para o método. No segundo, você precisaria instanciar uma lista e passá-la.
fonte