Passer juste un type comme paramètre en C #

130

Hypothétiquement, ce serait pratique pour moi de faire ceci:

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

où la méthode GetColumns appellera une méthode différente à l'intérieur en fonction du type passé.

Oui, je pourrais le faire comme un drapeau booléen ou similaire, je me suis juste demandé s'il y avait un moyen de peut-être passer cela, puis j'ai demandé:

typeof (arg [1]) ou similaire ...

Je pourrais aussi remplacer la méthode, utiliser des génériques, etc. - Je sais qu'il existe différentes façons de faire cela, j'étais juste curieux de savoir si cela était possible.

Mark Mayo
la source
Ma pensée exactement, en fonction de ce qu'est réellement foo. foo.GetColumnValues<int>(dm.mainColumn)peut être la voie à suivre.
Major Productions
1
Comme je l'ai dit, je me rends compte qu'il existe d'autres façons de faire cela (drapeau booléen, génériques, remplacement de la méthode) Je me suis juste demandé si c'était possible en tant que paramètre.
Mark Mayo
@MarkMayo: Je ne comprends pas la question si vous "savez que vous pouvez aussi remplacer la méthode, utiliser des génériques, etc. et vous savez qu'il existe différentes façons de faire cela, vous étiez simplement curieux de savoir si c'était possible" . Alors vous savez tout cela mais vous êtes curieux de savoir si c'est possible ??
Tim Schmelter
@TimSchmelter - sous la forme que je décris. c'est-à-dire en le passant comme 2ème paramètre. En fait, Reed a en quelque sorte dit ce que je voulais - où vous utilisez (..., type Type). C'est ce que je cherchais.
Mark Mayo
1
Bonne question, votée pour moi, je vois MS utilisant Type comme paramètre pour les opérateurs intégrés dans VB.NET, par exemple trycast, et j'ai souvent souhaité pouvoir le faire moi-même en C # / VB - de la manière que vous décrivez.
Chalky

Réponses:

213

Il existe deux approches communes. Premièrement, vous pouvez passerSystem.Type

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

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

Cela s'appellerait comme: int val = (int)GetColumnValue(columnName, typeof(int));

L'autre option serait d'utiliser des génériques:

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

Cela a l'avantage d'éviter la boxe et d'offrir une certaine sécurité de type, et s'appellerait comme: int val = GetColumnValue<int>(columnName);

Reed Copsey
la source
1
Vous pouvez également faire une méthode d'extension, public static T GetColumnValue <T> (this string columnName) {...} puis vous pouvez dire foo.GetColumnValues ​​<string> (dm.mainColumn)
Joshua G
Mais comment définir une méthode qui a plusieurs arguments et l'un d'eux devrait être un générique? Puisque le générique est défini avant la liste d'arguments de méthode, comment savoir lequel doit être un générique alors?
BadmintonCat
5
@BadmintonCat T Foo<T,U>(string arg1, U arg2)ou similaire
Reed Copsey
Lors de l'utilisation de la première approche, existe-t-il un moyen d'attribuer une valeur par défaut au type? (par exemple quelque chose comme object GetColumnValue(string columnName, Type type = object)? Cela ne semble pas tout à fait fonctionner pour moi, mais il serait utile de savoir.
Dave Cole
22

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

Vous pouvez également utiliser une méthode générique:

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

et vous pouvez ensuite l'utiliser comme:

foo.GetColumnValues<string>(dm.mainColumn);
Peter Ritchie
la source
13

Vous pouvez passer un type comme argument, mais pour ce faire, vous devez utiliser typeof:

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

La méthode devrait accepter un paramètre avec type Type.


où la méthode GetColumns appellera une méthode différente à l'intérieur en fonction du type passé.

Si vous souhaitez ce comportement, vous ne devez pas passer le type en tant qu'argument, mais plutôt utiliser un paramètre de type.

foo.GetColumnValues<int>(dm.mainColumn)
Mark Byers
la source
8
foo.GetColumnValues(dm.mainColumn, typeof(int));
foo.GetColumnValues(dm.mainColumn, typeof(string));

Ou en utilisant des génériques:

foo.GetColumnValues<int>(dm.mainColumn);
foo.GetColumnValues<string>(dm.mainColumn);
Danny Varod
la source
3
Je ne vous ai pas fait de dv, mais c'est probablement parce que vous montrez comment il serait appelé et que vous n'avez pas spécifié la définition de la fonction
JConstantine
3
Je déteste quand les gens ont besoin d'une cuillère. La réponse + une lecture très brève de MSDN suffit. Je soupçonne que les électeurs à la baisse sont des répondants en concurrence avec les représentants - combien mesquins.
Danny Varod
1

Vous pouvez le faire, enveloppez-le simplement typeof()

foo.GetColumnValues(typeof(int))

public void GetColumnValues(Type type)
{
    //logic
}
Kevin DiTraglia
la source
0

Vous pouvez utiliser un argument de type Type - iow, passez typeof (int). Vous pouvez également utiliser des génériques pour une approche (probablement plus efficace).

500 - Erreur de serveur interne
la source
0

Utilisez des types génériques!

  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;
    }
}

Et appelez-le comme ceci:

  DataExtraction<AdPerformanceRow> extractor = new DataExtraction<AdPerformanceRow>(dates, predicates , cids);
Boris Detry
la source