c# - 如何使 for 循环成为通用的?
问题描述
一个 for 循环
for (T i = a; i < b; i++)
{
// do something
}
看起来很正常,对吧?
再看一眼,您会注意到T
不是原始数据类型 - 泛型类型。仍然不应该是一个问题,你会想。T
可以是任何东西, 不限于 数字(字符串,甚至是复杂对象),只要它具有可比性和可枚举性(即您需要对其应用约束where T: IEnumerable, IComparable
)。
因为它不仅限于数字,而且由于 Eric 给出的答案适用于任何类型的对象,我不认为这个问题与“是否存在限制我的通用方法数字类型?”
但回到这个问题:我也是这么想的,然后我开始玩弄这个问题并尝试写一些类似的东西
IEnumerable<T> Numbers<T>(T a, T b)
where T: IEnumerable, IComparable
{
for (T i = a; i < b; i++)
{
yield return i;
}
}
实现一个可用于 double、int、... 的数字生成器,这将是一个通用的 for 循环。约束IEnumerable
和 IComparable
只是告诉编译器可以枚举和比较这种类型的元素(因为循环中的i < b
表达式for
和增量),如果 C# 有这个,INumeric也是一个非常有用的约束(当然,这将隐含地具有可比性和可枚举性)。
令我惊讶的是,此示例无法编译,它会生成以下错误:
CS0019:运算符“<”不能应用于“T”类型的操作数和“T”
CS0023:运算符“++”不能应用于“T”类型的操作数
原因似乎是对数字没有限制,但似乎没有任何实用的解决方案可用,正如这里的一些答案所解释的那样。
注意:类似的(非通用)版本可以编译:
IEnumerable<double> Numbers(double a, double b)
{
for (var i = a; i < b; i++)
{
yield return i;
}
}
IEnumerable<int> Numbers(int a, int b)
{
for (var i = a; i < b; i++)
{
yield return i;
}
}
如果你有两者,你可以像调用它一样
var intNumbers = Numbers((int)1, 10);
var doubleNumbers = Numbers((double)1, 10);
并且由于参数的签名,选择了正确的版本。
本质上,问题是:
1.是否可以编写一个通用函数作为可以调用的函数
var intNumbers = Numbers<int>(1, 10);
var doubleNumbers = Numbers<double>(1, 10);
如我的第一个示例所示?
(我不确定正确的约束,我认为这样where T: IEnumerable, IComparable
做是因为您需要比较i < b
并且需要迭代到下一个更大的数字)。
2. a) 我如何编写一个通用约束来增加和比较类型变量T
?
2. b) 如果没有这样的约束,有没有办法用通用参数模拟 for 循环?
3. 如何使 for 循环成为通用的?
解决方案
一个for
循环有四个部分:
- 初始化当前状态
- 测试当前状态,如果测试失败则停止
- 执行一个动作
- 创建一个新的当前状态
我们将离开它break
,continue
因为它们使事情变得相当复杂。
您希望将操作限制为产生值。美好的。那么我们想要的是Aggregate
产生一个值的新版本:
public static IEnumerable<R> MyFor<S, R>(
S initial,
Func<S, bool> test,
Func<S, S> increment,
Func<S, R> select)
{
for (S current = initial; test(current); current = increment(current))
yield return select(current);
}
我们完成了。您现在可以for
通过简单地提供必要的 lambdas 来制作您喜欢的任何循环:
static IEnumerable<double> MakeDoubles() =>
MyFor(0.0, x => x <= 10.0, x => x + 1.0, x => x);
推荐阅读
- django - django 多对多字段保存
- regex - 字符串匹配的正则表达式 ****${****}***
- php - 这是什么意思...为什么视图前有一个 $ 符号。即@extends($master)
- prestashop - Prestashop 1.7 客户订单历史购物车问题
- python - 如何删除pyqt4中的整行(qtable小部件)
- google-chrome-extension - 清单包含不属于开发人员的无效搜索提供程序 url - chrome 扩展
- ios - 迅速避免数据竞争条件
- javascript - 通过此数组js将项目添加到循环中的数组
- javascript - 反应原生,如何将剪贴板中的文本粘贴到文本输入中
- wolfram-language - 这个 Wolfram 输出中的 True 是什么意思?