Chcę powiedzieć:
public void Problem(Guid optional = Guid.Empty)
{
}
Ale kompilator narzeka, że Guid.Empty nie jest stałą czasową kompilacji.
Ponieważ nie chcę zmieniać interfejsu API, nie mogę użyć:
Nullable<Guid>
c#
c#-4.0
optional-parameters
Ian Ringrose
źródło
źródło
Nullable<Guid> optional = null
(lub bardziej zwięźleGuid? optional = null
)? Wszelkie Guidy aktualnie przekazane do niego będą wymuszane bez konieczności wprowadzania jakichkolwiek zmian w kodzie.Odpowiedzi:
Rozwiązanie
Możesz użyć
new Guid()
zamiast tegoMożesz także użyć
default(Guid)
default(Guid)
również będzie działać dokładnie tak, jaknew Guid()
.Ponieważ Guid jest typem wartości, a nie typem referencyjnym, więc
default(Guid)
nie jest równynull
na przykład, zamiast tego jest równy wywołaniu domyślnego konstruktora.Co oznacza, że:
Jest dokładnie taki sam jak oryginalny przykład.
Wyjaśnienie
Dlaczego nie
Guid.Empty
zadziałało?Powód, dla którego otrzymujesz błąd, jest
Empty
następujący:Jest to więc zmienna, a nie stała (zdefiniowana jako
static readonly
nie jakoconst
). Kompilator może mieć tylko wartości znane kompilatorowi jako wartości domyślne parametrów metody (nie znane tylko w czasie wykonywania).Główną przyczyną jest to, że nie możesz mieć
const
żadnegostruct
, w przeciwieństwieenum
do na przykład. Jeśli spróbujesz, nie skompiluje się.Powód jest taki, że
struct
nie jest to typ prymitywny.Aby zapoznać się z listą wszystkich typów pierwotnych w .NET, zobacz http://msdn.microsoft.com/en-gb/library/system.typecode.aspx
(zauważ, że
enum
zwykle dziedziczyint
, co jest prymitywem)Ale
new Guid()
nie jest też stałą!Nie mówię, że to wymaga stałej. Potrzebuje czegoś, co można zdecydować w czasie kompilacji.
Empty
jest polem, więc jego wartość nie jest znana w czasie kompilacji (tylko na samym początku działania).Domyślna wartość parametru musi być znana w czasie kompilacji, która może być
const
wartością lub czymś zdefiniowanym za pomocą funkcji C #, która sprawia, że wartość jest znana w czasie kompilacji, na przykładdefault(Guid)
lubnew Guid()
(co jest ustalane w czasie kompilacji dlastruct
s, ponieważ nie można modyfikowaćstruct
konstruktora w kod).Chociaż możesz podać
default
lubnew
łatwo, nie możesz podaćconst
(ponieważ nie jest to typ pierwotny ani,enum
jak wyjaśniono powyżej). Tak więc, ponownie, nie mówiąc, że opcjonalny parametr sam w sobie wymaga stałej, ale wartość znana kompilatorowi.źródło
new Guid()
na przykład nie jest wyrażeniem stałym. Specyfikacja języka C # dość jasno definiuje, co jest dozwolone, w tym między innymi stałe. (Żeby było jasne, w praktyce jest to stała czasu kompilacji, ale nie jest „stałym wyrażeniem” w terminach C # spec).default
dzisiaj :)Guid.Empty
jest równoważne znew Guid()
, co jest równoważne zdefault(Guid)
. Możesz więc użyć:lub
Należy pamiętać, że
new Foo()
wartość ma zastosowanie tylko wtedy, gdy:Foo
jest typem wartościInnymi słowy, gdy kompilator wie, że tak naprawdę jest to tylko domyślna wartość typu :)
(Co ciekawe, jestem na 99,9% pewien, że nie wywoła żadnego niestandardowego
new Foo()
konstruktora, który mógłbyś stworzyć. Nie możesz utworzyć takiego konstruktora w typie wartości w C #, ale możesz to zrobić w IL.)Możesz użyć tej
default(Foo)
opcji dla dowolnego typu.źródło
Nullable<Guid>
potencjalnie.Nie możesz użyć:
default ( Guid )
?źródło
Operator '??' cannot be applied to operands of type 'System.Guid' and 'System.Guid'
Zaakceptowana odpowiedź nie działa w ASP.NET MVC i powoduje ten błąd w czasie wykonywania:
Zamiast tego możesz wykonać następujące czynności:
źródło
Kompilator jest całkiem poprawny;
Guid.Empty
nie jest stałą czasu kompilacji. Możesz spróbować przeciążać metodę w następujący sposób:źródło
Guid x = default(Guid)
rozwiązaniem, pamiętaj, że dodanie kolejnej funkcji przeciążenia nie komplikuje API bardziej niż dodanie opcjonalnego argumentu. I tak naprawdę to robi opcjonalny argument.