Eu gostaria de dizer:
public void Problem(Guid optional = Guid.Empty)
{
}
Mas o compilador reclama que Guid.Empty não é uma constante de tempo de compilação.
Como não desejo alterar a API, não posso usar:
Nullable<Guid>
c#
c#-4.0
optional-parameters
Ian Ringrose
fonte
fonte
Nullable<Guid> optional = null
(ou mais rapidamenteGuid? optional = null
)? Qualquer Guid passado a ele será coagido sem nenhuma alteração de código necessária.Respostas:
Solução
Você pode usar
new Guid()
em vezVocê também pode usar
default(Guid)
default(Guid)
também funcionará exatamente comonew Guid()
.Como Guid é um tipo de valor, não um tipo de referência, portanto,
default(Guid)
não é igual a,null
por exemplo, em vez disso, é igual a chamar o construtor padrão.O que significa que isso:
É exatamente o mesmo que o exemplo original.
Explicação
Por que não
Guid.Empty
funcionou?O motivo pelo qual você está recebendo o erro é porque
Empty
é definido como:Portanto, é uma variável, não uma constante (definida como
static readonly
não comoconst
). O compilador pode ter apenas valores conhecidos do compilador como valores padrão dos parâmetros do método (não somente conhecidos em tempo de execução).A causa raiz é que você não pode ter
const
nenhumstruct
, ao contrárioenum
do exemplo. Se você tentar, ele não será compilado.A razão mais uma vez é que
struct
não é um tipo primitivo.Para obter uma lista de todos os tipos primitivos no .NET, consulte http://msdn.microsoft.com/en-gb/library/system.typecode.aspx
(observe que
enum
geralmente herdaint
, que é uma primitiva)Mas
new Guid()
também não é uma constante!Não estou dizendo que precisa de uma constante. Precisa de algo que possa ser decidido em tempo de compilação.
Empty
é um campo, portanto, seu valor não é conhecido no tempo de compilação (apenas no início do tempo de execução).O valor padrão do parâmetro deve ser conhecido em tempo de compilação, que pode ser um
const
valor, ou algo definido usando um recurso C # que torna o valor conhecido em tempo de compilação, comodefault(Guid)
ornew Guid()
(que é decidido em tempo de compilação porstruct
s, pois você não pode modificar ostruct
construtor em código).Embora você possa fornecer
default
ounew
facilmente, você não pode fornecer umconst
(porque não é um tipo primitivo ouenum
como explicado acima). Portanto, novamente, sem dizer que o parâmetro opcional em si precisa de um valor constante, mas conhecido do compilador.fonte
new Guid()
não é uma expressão constante, por exemplo. A especificação C # define claramente o que é permitido, incluindo mas não limitado a constantes. (Só para ficar claro, ele efetivamente é uma constante de tempo de compilação, não apenas uma "expressão constante" em termos C # especificação).default
hoje :)Guid.Empty
é equivalente anew Guid()
, que é equivalente adefault(Guid)
. Então você pode usar:ou
Observe que o
new Foo()
valor é aplicável apenas quando:Foo
é um tipo de valorEm outras palavras, quando o compilador sabe que é realmente apenas o valor padrão para o tipo :)
(Curiosamente, tenho 99,9% de certeza de que ele não chamará nenhum
new Foo()
construtor personalizado que você possa ter criado. Você não pode criar esse construtor em um tipo de valor em C #, mas pode fazê-lo em IL.)Você pode usar a
default(Foo)
opção para qualquer tipo.fonte
Nullable<Guid>
, potencialmente.Você não pode usar:
default ( Guid )
?fonte
Operator '??' cannot be applied to operands of type 'System.Guid' and 'System.Guid'
A resposta aceita não funciona no ASP.NET MVC e causa este erro em tempo de execução:
Em vez disso, você pode fazer o seguinte:
fonte
O compilador está bastante correto;
Guid.Empty
não é uma constante em tempo de compilação. Você pode tentar sobrecarregar um método como este:fonte
Guid x = default(Guid)
a solução, lembre-se de que adicionar outra sobrecarga de função não complica a API mais do que adicionar um argumento opcional. Isso é realmente o que um argumento opcional faz de qualquer maneira.