2012-03-05 17 views
16

Powiel możliwe:
C# optional parameters on overridden methodsCzy możesz wyjaśnić mi dziwne zachowanie C# z opcjonalnymi argumentami?

Jest to wyjście z następującego kodu:

Peter: -1 
Peter: 0 
Fred: 1 
Fred: 1 

Czy możesz mi wyjaśnić, dlaczego rozmowa z Piotrem p.TellYourAge() i p.DoSomething() nie jest identyczny?

Oto kod, aby spróbować samemu (VS2010 i FW 4):

static void Main(string[] args) 
    { 
     Peter p = new Peter(); 
     p.TellYourAge(); // expected -1, result: -1 
     p.DoSomething(); // expected -1, result: 0 

     Fred f = new Fred(); 
     f.TellYourAge(1); // expected 1, result: 1 
     f.DoSomething(); // expected 1, result: 1 

     Console.ReadKey(); 
    } 
} 

public abstract class Person 
{ 
    public abstract void TellYourAge(int age); // abstract method without default value 
} 

public class Peter : Person 
{ 
    public override void TellYourAge(int age = -1) // override with default value 
    { 
     Console.WriteLine("Peter: " + age); 
    } 

    public void DoSomething() 
    { 
     TellYourAge(); 
    } 
} 

public class Fred : Person 
{ 
    public override void TellYourAge(int age) // override without default value 
    { 
     Console.WriteLine("Fred: " + age); 
    } 

    public void DoSomething() 
    { 
     TellYourAge(1); 
    } 
} 
+2

Moje pierwsze przypuszczenie, że skoro nie ma pustych int tutaj: public override void TellYourAge (int age = -1) // przesłonić z domyślnej wartości, to domyślnie jest zawsze 0 ... – mservidio

+2

@mservidio Ale dlatego określasz domyślną wartość –

+1

Możesz być zainteresowany [tym artykułem] (http://blogs.msdn.com/b/ericlippert/archive/2011/05/09/optional-argument-corner-cases-part-one. aspx) autorstwa Eric Lippert. Chociaż nie opisuje dokładnie tego samego przypadku, powinien dać ci kilka wskazówek na temat tego, co się dzieje. –

Odpowiedz

3

Jeśli zdarzy się użyć ReSharper, to daje następujące ostrzeżenie/zawiadomienie.

"Wartość domyślna parametru opcjonalnego różni się od wieku parametru w metodzie podstawowej nieważność TellYourAge (int age)."

Sprawdź, kiedy mieszasz opcjonalne wartości parametrów i dziedziczenie. Domyślne wartości parametrów są rozwiązywane w czasie kompilacji, a nie w czasie wykonywania. Wartość domyślna należy do wywoływanego typu referencyjnego. Tutaj rozpatruje typ Person i wykorzystuje domyślną wartość liczby całkowitej, która wynosi 0, zamiast -1.

można znaleźć informacje na temat typowych pułapek związanych opcjonalne parametry tutaj:

http://geekswithblogs.net/BlackRabbitCoder/archive/2010/06/17/c-optional-parameters---pros-and-pitfalls.aspx

łatwo naprawić, jeśli chcesz użyć go w ten sposób. Jawnie określ słowo kluczowe "this" podczas wywoływania metody TellYourAge. W ten sposób żądana wartość domyślna zostanie określona w czasie kompilacji.

public void DoSomething() 
{ 
    this.TellYourAge(); 
} 
+1

Spodziewałbym się w tym przypadku błędu kompilacji lub ostrzeżenia, ale nie o to chodzi. To, że parametry domyślne są rozwiązywane w czasie kompilacji, jest również jasne, ale nie wyjaśnia, dlaczego dokładnie to samo wywołanie funkcji TellYourAge() na instancji p powoduje różne wyniki. – X181

+0

Zobacz także http://blogs.msdn.com/b/ericlippert/archive/2011/05/09/optional-argument-corner-cases-part-one.aspx –

+1

Tematy są powiązane, ale nie są duplikatem. W drugim przypadku używana jest określona wartość domyślna. W tym przypadku używana jest nieokreślona domyślna wartość typu. – X181

Powiązane problemy