2008-10-17 16 views
6

tengo una clase genérica en C# con 2 constructores:con C# params palabra clave en un constructor de tipos genéricos

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

La construcción de un objeto utilizando int como el tipo genérico y pasando en dos enteros como argumentos hace que el ' constructor incorrecto a ser llamado (desde mi punto de vista).

E.g. Houses<int> houses = new Houses<int>(1,2) - llama al segundo construtor. Al pasar en cualquier otra cantidad de entradas al constructor se llamará al primer constructor.

¿Hay alguna forma de evitar esto que eliminar la palabra clave params y forzar a los usuarios a pasar una matriz de T cuando se usa el primer constructor?

Respuesta

13

Una solución más clara sería tener dos métodos de fábrica estáticos. Si coloca estos en una clase no genérica, también puede beneficiarse de la inferencia de tipos:

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

Ejemplo de invocación:

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

A continuación, el constructor de su tipo genérico no necesita el "params" bits, y no habrá confusión

2

Tal vez en lugar de Parámetros que podría pasar en IEnumerable

public Houses(IEnumerable<T> InitialiseElements){} 
2

El segundo constructor es una forma más exacta partido, que es el criterio utilizado para evaluar qué constructor es correcta.

2

Dada la siguiente ya que el original no tenían demasiada información en la clase, etc.

El compilador va a decidir Casa nueva (1,2) coincide con el segundo constructor exactamente y usar eso, observe que me tomó la respuesta con más votos y no funcionó.

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