Utilisation du mot clé params C # dans un constructeur de types génériques

StackOverflow https://stackoverflow.com/questions/213333

  •  03-07-2019
  •  | 
  •  

Question

J'ai une classe générique en C # avec 2 constructeurs:

public Houses(params T[] InitialiseElements)
{}
public Houses(int Num, T DefaultValue)
{}

Construire un objet en utilisant int comme type générique et en passant deux ints en arguments provoque l'appel du constructeur "incorrect" (de mon point de vue).

E.g. Houses<int> houses = new Houses<int>(1,2) - appelle le 2e constructeur. Si vous entrez un nombre différent d’entités dans le constructeur, le premier constructeur sera appelé.

Existe-t-il un moyen autre que de supprimer le mot clé params et d'obliger les utilisateurs à passer un tableau de T lors de l'utilisation du premier constructeur?

Était-ce utile?

La solution

Une solution plus claire serait d’avoir deux méthodes d’usine statique. Si vous les mettez dans une classe non générique, vous pouvez également bénéficier de l'inférence de type:

public static class Houses
{
    public static Houses<T> CreateFromElements<T>(params T[] initialElements)
    {
        return new Houses<T>(initialElements);
    }

    public Houses<T> CreateFromDefault<T>(int count, T defaultValue)
    {
        return new Houses<T>(count, defaultValue);
    }
}

Exemple d'appel:

Houses<string> x = Houses.CreateFromDefault(10, "hi");
Houses<int> y = Houses.CreateFromElements(20, 30, 40);

Ensuite, le constructeur de votre type générique n'a pas besoin de " params " peu, et il n'y aura pas de confusion.

Autres conseils

Peut-être qu'au lieu de Params, vous pourriez passer en IEnumerable

public Houses(IEnumerable<T> InitialiseElements){}

Le deuxième constructeur est une correspondance plus exacte , qui est le critère utilisé pour évaluer quel constructeur est correct.

Étant donné que l’original n’avait pas trop d’informations sur la classe, etc.,

Le compilateur va décider que la nouvelle Maison (1,2) correspond exactement au deuxième constructeur et utilise cela, remarquez que j'ai pris la réponse avec le plus grand nombre de votes et que cela n'a pas fonctionné.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GenericTest
{
    public class House<T>
    {
        public House(params T[] values)
        {
            System.Console.WriteLine("Params T[]");
        }
        public House(int num, T defaultVal)
        {
            System.Console.WriteLine("int, T");
        }

        public static House<T> CreateFromDefault<T>(int count, T defaultVal)
        {
            return new House<T>(count, defaultVal);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            House<int> test = new House<int>(1, 2);                         // prints int, t
            House<int> test1 = new House<int>(new int[] {1, 2});            // prints parms
            House<string> test2 = new House<string>(1, "string");           // print int, t
            House<string> test3 = new House<string>("string", "string");    // print parms
            House<int> test4 = House<int>.CreateFromDefault<int>(1, 2);     // print int, t
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top