Przekazywanie tylko typu jako parametru w C #

130

Hipotetycznie przydałoby mi się to zrobić:

foo.GetColumnValues(dm.mainColumn, int)
foo.GetColumnValues(dm.mainColumn, string)

gdzie metoda GetColumns wywoła inną metodę w zależności od przekazanego typu.

Tak, mógłbym to zrobić jako flagę logiczną lub coś podobnego, po prostu zastanawiałem się, czy istnieje sposób, aby to przekazać, a następnie zapytałem:

typeof (arg [1]) lub podobny ...

Mógłbym również zastąpić metodę, użyć generycznych itp. - Wiem, że są na to różne sposoby, byłem po prostu ciekawy, czy to możliwe.

Mark Mayo
źródło
Myślałem dokładnie, w zależności od tego, czym właściwie jest foo. foo.GetColumnValues<int>(dm.mainColumn)może być drogą do zrobienia.
Major Productions
1
Jak powiedziałem, zdaję sobie sprawę, że są inne sposoby, aby to zrobić (flaga boolowska, typy generyczne, przesłanianie metody). Zastanawiałem się tylko, czy jest to możliwe jako parametr.
Mark Mayo
@MarkMayo: Nie rozumiem pytania, jeśli „wiesz, że możesz również zastąpić metodę, użyć leków generycznych itp. I wiesz, że są na to różne sposoby, byłeś po prostu ciekawy, czy to jest możliwe” . Więc wiesz to wszystko, ale jesteś ciekawy, czy to możliwe?
Tim Schmelter
@TimSchmelter - w opisanej przeze mnie formie. czyli przekazanie go jako drugiego parametru. Jak się okazuje, Reed powiedział trochę, o co mi chodzi - gdzie używasz (..., typ Type). Tego właśnie szukałem.
Mark Mayo
1
Dobre pytanie, przegłosowane, widzę, że MS używa Type jako parametru dla wbudowanych operatorów w VB.NET, np. Trycast, i często żałowałem, że nie mogę tego zrobić sam w C # / VB - w sposób, który opisujesz.
Chalky

Odpowiedzi:

213

Istnieją dwa popularne podejścia. Po pierwsze, możesz przejśćSystem.Type

object GetColumnValue(string columnName, Type type)
{
    // Here, you can check specific types, as needed:

    if (type == typeof(int)) { // ...

Nazywa się to następująco: int val = (int)GetColumnValue(columnName, typeof(int));

Inną opcją byłoby użycie leków generycznych:

T GetColumnValue<T>(string columnName)
{
    // If you need the type, you can use typeof(T)...

Ma to tę zaletę, że pozwala uniknąć boksowania i zapewnia pewien rodzaj bezpieczeństwa, i byłoby nazywane: int val = GetColumnValue<int>(columnName);

Reed Copsey
źródło
1
Możesz również wykonać metodę rozszerzającą, public static T GetColumnValue <T> (this string columnName) {...}, a następnie możesz powiedzieć foo.GetColumnValues ​​<string> (dm.mainColumn)
Joshua G
Ale jak zdefiniować metodę, która ma kilka argumentów, a jeden z nich powinien być generyczny? Skoro rodzaj ogólny jest definiowany przed listą argumentów metody, skąd wiesz, który z nich powinien być generyczny?
BadmintonCat
5
@BadmintonCat T Foo<T,U>(string arg1, U arg2)lub podobny
Reed Copsey
Czy w przypadku pierwszego podejścia istnieje sposób przypisania wartości domyślnej do typu? (np. coś w stylu object GetColumnValue(string columnName, Type type = object)? To nie wydaje się działać dla mnie, ale warto wiedzieć.
Dave Cole
22

foo.GetColumnValues(dm.mainColumn, typeof(string))

Alternatywnie możesz użyć ogólnej metody:

public void GetColumnValues<T>(object mainColumn)
{
    GetColumnValues(mainColumn, typeof(T));
}

i możesz wtedy użyć go tak:

foo.GetColumnValues<string>(dm.mainColumn);
Peter Ritchie
źródło
13

Możesz przekazać typ jako argument, ale aby to zrobić, musisz użyć typeof:

foo.GetColumnValues(dm.mainColumn, typeof(int))

Metoda musiałaby akceptować parametr z typem Type.


gdzie metoda GetColumns wywoła inną metodę w zależności od przekazanego typu.

Jeśli chcesz tego zachowania, nie powinieneś przekazywać typu jako argumentu, ale zamiast tego użyj parametru typu.

foo.GetColumnValues<int>(dm.mainColumn)
Mark Byers
źródło
8
foo.GetColumnValues(dm.mainColumn, typeof(int));
foo.GetColumnValues(dm.mainColumn, typeof(string));

Lub używając typów ogólnych:

foo.GetColumnValues<int>(dm.mainColumn);
foo.GetColumnValues<string>(dm.mainColumn);
Danny Varod
źródło
3
Nie rozmawiałem z tobą, ale to prawdopodobnie dlatego, że pokazujesz, jak zostanie wywołany i nie określiłeś definicji funkcji
JConstantine
3
Nienawidzę, kiedy ludzie potrzebują karmienia łyżeczką. Odpowiedź + naprawdę krótkie przeczytanie MSDN wystarczy. Podejrzewam, że ci, którzy stracili głos, konkurują o reprezentantów - jakie to małostkowe.
Danny Varod
1

Możesz to zrobić, po prostu zawiń typeof()

foo.GetColumnValues(typeof(int))

public void GetColumnValues(Type type)
{
    //logic
}
Kevin DiTraglia
źródło
0

Możesz użyć argumentu typu Type - iow, przekazać typeof (int). Możesz także użyć leków generycznych, aby uzyskać (prawdopodobnie bardziej wydajne) podejście.

500 wewnętrzny błąd serwera
źródło
0

Używaj typów ogólnych!

  class DataExtraction<T>
{
    DateRangeReport dateRange;
    List<Predicate> predicates;
    List<string> cids;

    public DataExtraction( DateRangeReport dateRange,
                           List<Predicate> predicates,
                           List<string> cids)            

    {
        this.dateRange = dateRange;
        this.predicates = predicates;
        this.cids = cids;
    }
}

I nazwij to tak:

  DataExtraction<AdPerformanceRow> extractor = new DataExtraction<AdPerformanceRow>(dates, predicates , cids);
Boris Detry
źródło