此问题已在此处有答案:
Is there a constraint that restricts my generic method to numeric types?(24回答)
4年前关闭。
这篇文章是编辑并提交审查16小时前.
一个for循环
for (T i = a; i < b; i++)
{
// do something
}
看起来很正常对吧
再看一眼,您会注意到T
而不是原始数据类型-泛型类型。这不应该是一个问题,你会想。T
可以是任何值, 不限于 一个数字(一个字符串,甚至一个复杂的对象),只要它是可比较和可枚举的(即您需要将约束where T: IEnumerable, IComparable
应用于它)。
因为它不限于数字,而且Eric给出的答案适用于任何类型的对象我不相信这个问题是"Is there a constraint that restricts my generic method to numeric types?"问题的重复
但回到这个问题:我也是这么想的,然后我开始尝试写一些类似的东西
IEnumerable<T> MyFor<T>(T a, T b)
where T: IEnumerable, IComparable
{
for (T i = a; i < b; i++)
{
yield return i;
}
}
实现一个数字生成器,可用于double,int,…这将是一个通用的for循环。约束IEnumerable
和IComparable
只是告诉编译器,这种类型的元素可以被枚举和比较(因为for
循环中的i < b
表达式和增量),如果C#有这样的约束,INumeric也会是一个非常有用的约束(当然,它会隐含地是可比较和可枚举的)。
令我惊讶的是,这个例子无法编译,它生成了以下错误:
CS 0019:运算符“<”不能应用于类型为“T”和“T”的操作数
CS 0023:运算符“++”不能应用于类型为“T”的操作数
原因似乎是数字没有约束,但似乎没有任何实际的解决方案,正如一些答案here所解释的那样。
**注意:**类似的(非通用)版本可以编译:
IEnumerable<double> MyFor(double a, double b)
{
for (var i = a; i < b; i++)
{
yield return i;
}
}
IEnumerable<int> MyFor(int a, int b)
{
for (var i = a; i < b; i++)
{
yield return i;
}
}
IEnumerable<string> MyFor(string a, string b)
{
for (string i = a; i.Length < b.Length; i = i + a)
{
yield return i;
}
}
如果像上面所示的那样重载了它,则可以像下面这样调用它:
var intNumbers = MyFor((int)1, 10);
var doubleNumbers = MyFor((double)1, 10);
var stringFor = MyFor("*", "abcde");
并且由于参数的签名而选择正确的版本。当然,这并不优雅,因为您只是为了使用不同的数据类型而复制代码。
本质上,为了使代码更优雅,更少冗余,问题是:
1.有没有可能写一个泛型函数,就像那样调用
var intNumbers = MyFor<int>(1, 10);
var doubleNumbers = MyFor<double>(1, 10);
var stringFor = MyFor<string>("*", "abcde");
如第一个例子所示。
(我不确定正确的约束,我认为where T: IEnumerable, IComparable
可以,因为你需要比较i < b
,你需要迭代到下一个更大的数字)。
2. a)如何编写一个泛型约束,允许我递增和比较T
类型的变量?
2. B)如果没有这样的约束,有没有一种方法可以用泛型参数模拟for循环?
3.如何使for循环成为泛型?
2条答案
按热度按时间3npbholx1#
for
循环有四个部分:我们将把
break
和continue
排除在外,因为它们使事情变得相当复杂。您希望将操作限制为 * 生成一个值 *。好吧,我们需要的是一个新版本的
Aggregate
,它会产生一个值:我们就结束了现在,你可以通过简单地提供必要的lambda表达式来创建任何你喜欢的
for
循环:s3fp2yjn2#
问题是,目前C#中没有可以以通用方式使用的“数字”约束。
因此,像这样使用泛型类型
T
的for循环不起作用,因为编译器不允许它:for (T i = a; i < b; i++)
作为一种变通方法,我们必须使用
while
循环,并将struct
与IComparable
一起作为约束。yield
关键字没有任何限制,正常工作。取决于实施方式,即无论您是否希望有一个灵活的增量,有两个功能可以解决这个问题。
请考虑以下代码:
上面的例子是用
int
、double
和float
调用Numbers
,第三个例子使用了0.75
的增量。