2013-02-26 18 views
9

Tak, natknąłem się na odpowiedź przez Servy (https://stackoverflow.com/a/15098242/496680), a niektóre z jego kod robi to:Jakie są regulowane typ rodzajowy Parametry

public static int BinarySearch<TSource, TKey>(...) 

za metodę rozszerzenia, ale nazywa to tak:

arr.BinarySearch(...) 

Zapytałem i ktoś powiedział, że jest to domyślny rodzaj parametru. Przeszukałem je, ale nie znalazłem na nich żadnych informacji. Rozumiem, jak działają rodzaje ogólne, ale nie rozumiem, jak/kiedy ich używać.

  1. Dlaczego serwis wykorzystuje je w swojej metodzie ekstention?
  2. Czy istnieje bardziej oficjalna nazwa dla tych, które mogę wyszukać?
+2

Mogę odpowiedzieć na pytanie nr 1 po prostu. Pozwala to na pracę z dowolnym typem kolekcji, a nie tylko na łańcuchach lub intach, Foos czy cokolwiek innego. Pozwala także na porównanie z dowolnym typem wartości, niech to będzie int lub string lub pasek lub [...]. W twoim konkretnym przypadku wystarczy wybrać 'int' z tablicy jakiegoś typu (że nawet nie znałem nazwy umysłu). Używając generyków, będzie działać nie tylko w twoim przypadku, ale w każdym podobnym przypadku, który ma ten sam problem, ale z różnymi typami. Będzie to bardziej pomocne dla przyszłych użytkowników, którzy znajdą Twoje pytanie. – Servy

+0

@Servy dzięki! Dla przyszłych czytelników znalazłem również ten post: http://stackoverflow.com/questions/4885027/how-does-generic-type-inference-work-in-c- –

Odpowiedz

10

Pominąłem najważniejszą część, która sprawia, że ​​wszystko działa. Parametry typu może wnioskować o rzeczywistych parametrów obiektów przekazanych w

Na przykład:.

static class Extensions { 
    internal static IEnumerable<U> Test<T, U>(
            this IEnumerable<T> items, 
            Func<T, U> converter) { 
    foreach (T item in items) { 
     yield return converter(item); 
    } 
    } 
} 

To rozszerzenie metoda działa na dowolnym IEnumerable klasy i zamieni każdy element wyliczenia do innego typu w oparciu na podanym konwerterze. To są standardowe leki generyczne.

Teraz, istnieje wiele sposobów, aby wywołać tę metodę:

IEnumerable<int> values = Enumerable.Range<int>(1, 10); 
Func<int, string> converter = i => i.ToString("0.00"); 

// Variation 1, explicit calling 
IEnumerable<string> results1 = Extensions.Test<int, string>(values, converter); 

// Variation 2, explicit calling with type inference 
IEnumerable<string> results2 = Extensions.Test(values, converter); 

// Variation 3, extension method calling, still providing explicit types 
IEnumerable<string> results3 = values.Test<int, string>(converter); 

// Variation 4, extension method with type inference 
IEnumerable<string> results4 = values.Test(converter); 

Wszystkie cztery odmiany nazywają tę samą metodę i zwraca ten sam wynik. Inferencja typów działa, patrząc na parametry przekazane i automatycznie wnioskuje ich typy na podstawie dostarczanych informacji. W naszych przykładach powyżej można stwierdzić, że typ T jest typu int, ponieważ przekazaliśmy parametr IEnumerable<int> do parametru IEnumerable<T>. Jest również w stanie wywnioskować, że typ U jest typu string, ponieważ przeszliśmy w Func pasującym do początkowego typu T z int i zwracając ciąg znaków. Tak więc Func<T, U> jest wypełniony naszą funkcją konwertera Func<int, string>.

Z powyższego wywodu jest to standardowa metoda standardowa w tym punkcie. Metody wnioskowania i rozszerzenia są niczym więcej niż wygodą/cukrem syntaktycznym.W rzeczywistości, jeśli dekompilujesz dane wyjściowe, możesz zauważyć, że metody rozszerzeń są zastępowane przez wywołania statyczne i są zwykle definiowane z jawnie wypełnionymi parametrami typu. (To zależy od twojego dekompilatora i ustawionych opcji).

+0

W dwóch ostatnich przykładach należy pominąć "wartości" jako parametr. – Servy

+0

Ups, dzięki! To niesamowite, co możesz przegapić, gdy nie możesz się skompilować! – Joshua

+0

Świetne wyjaśnienie! dzięki! –

2

Termin, który zwykle słyszę, to "wnioskowanie o typie".

+0

Tak, nazywa się to "wnioskiem o typ". Jest całkiem podstawowy przykład w [Generic Methods (C# Programming Guide)] (http://msdn.microsoft.com/en-us/library/twcad0zb.aspx) gdzie jest napisane: _Można także pominąć argument type i kompilator ** wnioskuje **. Następujące wywołanie zamiany jest równoznaczne z poprzednim wywołaniem: [...] Te same reguły dla wnioskowania o typ mają zastosowanie do metod statycznych i metod instancji. Kompilator może wywnioskować parametry typu na podstawie argumentów metody, które przekazujesz; nie może wywnioskować parametrów typu tylko z ograniczenia lub wartości zwracanej. [...] _ –

6
  1. Używa generic method w tym przypadku, ponieważ umożliwia jego metoda pracy z wszelkiego rodzaju zawartego w Collection<T>. Ogólna metoda sprawia, że ​​jest to bardzo elastyczne i użyteczne dla każdego typu. Podczas wywoływania metody wykorzystuje infercję typu, ponieważ upraszcza kod w witrynie wywołania.

  2. Automatyczna obsługa jest nazywana przejmowaniem typu i jest szczegółowo opisana w Specyfikacji języka C#, sekcja 7.5.2: Wciąganie typu. Jeśli chcesz go dokładnie zrozumieć, polecam pobranie C# language specification.

Powiązane problemy