2013-06-23 12 views
5

Jak przejść z jednego instancji do innego? Przypuśćmy, że mamy tę klasę. Jak przejść z foo (string, string) do foo (Uri)?Konstruktor łańcuchowy przekazujący obliczone wartości dla parametrów

public foo 
{ 
    string path { get; private set; } 
    string query { get; private set; } 

    public foo (Uri someUrl) 
    { 
     // ... do stuff here 
    } 

    public foo (string path, string query) 
    { 
     Uri someUrl = new Uri(String.Concat(path, query); 

     // ... do stuff here to pass thru to foo(someUrl) 
    } 
} 
+0

Głosowanie w celu ponownego otwarcia. Odpowiedź w duplikacie jest poprawna, ale jest bardziej zorientowana na "prosty" parametr przekazywany do kolejnego konstruktora. PO post sugeruje, że istnieje pewne przetwarzanie do wykonania URI przed przekazaniem go dalej. Bardziej odpowiednią odpowiedzią byłoby posiadanie wspólnej metody, którą obaj konstruktorzy nazywają i przekazują parametry przez odniesienie. – keyboardP

+0

@keyboardP, zgadzam się z tobą. Zmodyfikowałem tytuł, aby dokładniej to odzwierciedlić i głosowałem za ponownym otwarciem. (również szukał duplikatów tego niuansu i pojawił się pusty) –

+0

Dzięki za ponowne otwarcie. –

Odpowiedz

4

można też zrobić coś takiego:

class Frob 
{ 
    public Frob (Uri uri) 
    { 

    } 

    public Frob(string path, string query) 
     : this(TidyUpUri(path, query)) 
    { 

    } 

    private static Uri TidyUpUri(string path, string query) 
    { 
     var uri = new Uri(string.Concat(path, query)); 

     // etc. 

     return uri; 
    } 
} 
+0

Awesome. To jest technika, którą wykorzystałem. Dzięki! –

7

Do prostego konstruktora łańcuchowych, można użyć specjalnych słów kluczowych this lub base się odnosić do innych konstruktorów bieżącego lub dominującej za klasę. Możesz używać parametrów konstruktora wykonawczego jako parametrów do powiązanego konstruktora i możesz łączyć je przy użyciu dowolnego pojedynczego wyrażenia zgodnego z . Jest to zasadniczo ta sama reguła, która ma zastosowanie do każdego innego wyrażenia wbudowanego dostarczanego do wywołania funkcji, z tym że powinieneś unikać używania jakichkolwiek elementów klasy (ponieważ nie została ona jeszcze zbudowana) i ograniczyć się do stałych i parametrów przekazujących:

public foo (Uri someUrl) 
{ 
    this.url = someUrl; 
} 

public foo (string path, string query) 
    : this(new Uri(String.Concat(path, query))) 
{ 
    // this.url is now set and available. 
} 

To będzie działać tak długo, jak przetwarzania, które trzeba zrobić, można zrobić w jednym wyrażeniu wartości. Jeśli potrzebujesz, na przykład, zrobienia czegoś innego z Uri, zanim zostanie ona wysłana do innego konstruktora, lub jeśli potrzebujesz skomplikowanej logiki, nie będziesz w stanie uciec z tą techniką. Alternatywą jest byłaby kodu do metody inicjalizacji:

public foo (Uri someUrl) 
{ 
    this.init(someUrl); 
} 

public foo (string path, string query) 
{ 
    var url = String.Concat(path, query); 
    url = url.Replace("http://", "https://"); 

    this.init(url); 
} 

private void init (Uri someUrl) 
{ 
    this.url = someUrl; 
} 
+1

Drobna nitpick, ale prawdopodobnie lepiej jest uczynić 'init' intymnym. –

+0

Rozumiem! Jeśli mam bardziej złożone wymagania dotyczące łączenia, następnym razem skonfiguruję init. Dzięki! –

2

Skoro przetwarzanie swoich strun przed przekazaniem ich razem, można wyodrębnić Do wspólna metoda. Na przykład

private void ProcessUri(ref Uri theUri) 
{ 
    //...do your URI stuff here 
} 

public foo (Uri someUrl) 
{ 
    ProcessUri(ref someUrl); 
} 

public foo (string path, string query) 
{ 
    Uri someUrl = new Uri(String.Concat(path, query)); 

    // ... do stuff here to pass then call ProcessUri 
    ProcessUri(ref someUrl); 
} 

Zaletą rzeczy mijających się z ref jest to, że można ustawić wartości readonly właściwości tak jak byś jeśli zmienna została ustawiona w konstruktorze.

Powiązane problemy