在泛型类型的构造函数中使用 C# params 关键字
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/213333/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using C# params keyword in a constructor of generic types
提问by sixtowns
I have a generic class in C# with 2 constructors:
我在 C# 中有一个具有 2 个构造函数的泛型类:
public Houses(params T[] InitialiseElements)
{}
public Houses(int Num, T DefaultValue)
{}
Constructing an object using int as the generic type and passing in two ints as arguments causes the 'incorrect' constructor to be called (from my point of view).
使用 int 作为泛型类型构造一个对象并传入两个 int 作为参数会导致调用“不正确”的构造函数(从我的角度来看)。
E.g. Houses<int> houses = new Houses<int>(1,2)
- calls the 2nd construtor. Passing in any other number of ints into the constructor will call the 1st constructor.
例如Houses<int> houses = new Houses<int>(1,2)
- 调用第二个构造函数。将任何其他数量的整数传入构造函数将调用第一个构造函数。
Is there any way around this other than removing the params keyword and forcing users to pass an array of T when using the first constructor?
除了删除 params 关键字并强制用户在使用第一个构造函数时传递 T 数组之外,还有其他方法可以解决这个问题吗?
采纳答案by Jon Skeet
A clearer solution would be to have two static factory methods. If you put these into a nongeneric class, you can also benefit from type inference:
更清晰的解决方案是拥有两个静态工厂方法。如果将它们放入非泛型类中,还可以从类型推断中受益:
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);
}
}
Example of calling:
调用示例:
Houses<string> x = Houses.CreateFromDefault(10, "hi");
Houses<int> y = Houses.CreateFromElements(20, 30, 40);
Then your generic type's constructor doesn't need the "params" bit, and there'll be no confusion.
那么你的泛型类型的构造函数就不需要“params”位,也就不会混淆了。
回答by Jon B
Perhaps instead of Params you could pass in IEnumerable
也许你可以传入 IEnumerable 而不是 Params
public Houses(IEnumerable<T> InitialiseElements){}
回答by Joel Coehoorn
The 2nd constructor is a more exactmatch, which is the criteria used to evaluate which constructor is correct.
第二个构造函数是更精确的匹配,这是用于评估哪个构造函数正确的标准。
回答by Jon Skeet
Given the following since the original did not have too much information on the class etc.
鉴于以下原因,原版没有太多关于课程等的信息。
The compiler is going to decide new House(1,2) matches the second constructor exactly and use that, notice that I took the answer with the most up votes and it did not work.
编译器将决定 new House(1,2) 与第二个构造函数完全匹配并使用它,请注意,我以最多的票数接受了答案,但它不起作用。
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
}
}
}