是否有一种常见的方法将单个类型的项传递给T需要IEnumerable<T>参数的方法 ?语言是C#,框架版本2.0.
目前我正在使用一个辅助方法(它是.Net 2.0,所以我有一大堆类似于LINQ的转换/投射辅助方法),但这看起来很愚蠢:
public static class IEnumerableExt
{
// usage: IEnumerableExt.FromSingleItem(someObject);
public static IEnumerable<T> FromSingleItem<T>(T item)
{
yield return item;
}
}
Run Code Online (Sandbox Code Playgroud)
其他方式当然是创建和填充a List<T>或an Array而不是传递它IEnumerable<T>.
[编辑]作为扩展方法,它可能被命名为:
public static class IEnumerableExt
{
// usage: someObject.SingleItemAsEnumerable();
public static IEnumerable<T> SingleItemAsEnumerable<T>(this T item)
{
yield return item;
}
}
Run Code Online (Sandbox Code Playgroud)
我在这里错过了什么吗?
[Edit2]我们发现someObject.Yield()(正如@Peter在下面的评论中所建议的那样)是这个扩展方法的最佳名称,主要是为了简洁,所以如果有人想要抓住它的话,它会与XML注释一起:
public static class IEnumerableExt
{
/// <summary>
/// Wraps this object instance into an IEnumerable<T>
/// consisting of a …Run Code Online (Sandbox Code Playgroud) IEnumerator包含MoveNext(),Reset()并Current作为其成员.现在假设我已将这些方法和属性移动到IEnumerable接口并删除了GetEnumerator()方法和IEnumerator接口.
现在,实现的类的对象IEnumerable将能够访问方法和属性,因此可以迭代.
IEnumerator接口的存在如何解决这些问题?我注意到List<T>它将枚举器定义为a struct,同时ArrayList将其枚举器定义为class.有什么不同?如果我要为我的班级写一个调查员,哪一个更好?
编辑:我的要求无法使用yield,所以我正在实现我自己的枚举器.也就是说,我想知道是否更好地遵循这些方法List<T>并将其作为结构实现.
我们知道不变性的概念,但除了需要知道几个不可变类型
还有更多吗?
我正在使用Reflector 查看Roslyn 2012年9月的CTP,我注意到ChildSyntaxList结构具有以下内容:
public struct ChildSyntaxList : IEnumerable<SyntaxNodeOrToken>
{
private readonly SyntaxNode node;
private readonly int count;
public Enumerator GetEnumerator()
{
return node == null ? new Enumerator() : new Enumerator(node, count);
}
IEnumerator<SyntaxNodeOrToken> IEnumerable<SyntaxNodeOrToken>.GetEnumerator()
{
return node == null
? SpecializedCollections.EmptyEnumerator<SyntaxNodeOrToken>()
: new EnumeratorImpl(node, count);
}
IEnumerator IEnumerable.GetEnumerator()
{
return node == null
? SpecializedCollections.EmptyEnumerator<SyntaxNodeOrToken>()
: new EnumeratorImpl(node, count);
}
public struct Enumerator
{
internal Enumerator(SyntaxNode node, int count)
{
/* logic */
}
public SyntaxNodeOrToken Current …Run Code Online (Sandbox Code Playgroud) 这是一个详细的答案,关于C#编译器foreach在IEnumerator<T>可变结构的情况下如何优化.
F#编译器是否执行相同的优化?
在这个答案和这个GitHub问题(顶部项目)中,有一个foreachC#编译器使用的优化描述.
基本上,IEnumerable<T>生成的代码调用GetEnumerator()然后MoveNext()在返回的对象上,而不是分配,总是使用直接call,因此避免装箱和虚拟调用.
是否可以用中间语言编写相同的逻辑?我是IL的初学者,但熟悉Unsafe包及其工作方式.我想知道是否有可能在IL中编写一个不安全的方法来接受一些对象并直接调用它的方法和属性?
(另外,有人可以提供一个链接到Roslyn仓库中的线路,这个foreach优化发生了吗?回购是如此之大和复杂,我到目前为止失去了.)
更新:
这是一个方法模板
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[ILSub(@"
.. IL code here to be replaced by ilasm.exe
.. Is there a way to do the same without boxing and virtual calls?
")]
public T CallIEnumerableMoveNextViaIL<T>(IEnumerable<T> enumerable)
{
// I know that the `enumerable` returns an enumerator that is a struct, but its type could be custom
// Next …Run Code Online (Sandbox Code Playgroud) c# ×6
.net ×4
cil ×1
enumeration ×1
f# ×1
generics ×1
ienumerable ×1
immutability ×1
roslyn ×1
vb.net ×1