在我的代码中需要使用IEnumerable<>几次因此得到Resharper错误"可能的多个枚举IEnumerable".
示例代码:
public List<object> Foo(IEnumerable<object> objects)
{
if (objects == null || !objects.Any())
throw new ArgumentException();
var firstObject = objects.First();
var list = DoSomeThing(firstObject);
var secondList = DoSomeThingElse(objects);
list.AddRange(secondList);
return list;
}
Run Code Online (Sandbox Code Playgroud)
objects参数List,然后避免可能的多次枚举,但后来我没有得到我能处理的最高对象. IEnumerable到List在方法的开头: public List<object> Foo(IEnumerable<object> objects)
{
var objectList = objects.ToList();
// ...
}
Run Code Online (Sandbox Code Playgroud)
但这只是尴尬.
在这种情况下你会做什么?
为什么在.NET 4.5 中List<T>实现IReadOnlyList<T>?
List<T> 不是只读的......
我的问题与此问题有些相关:显式实现的接口和通用约束.
然而,我的问题是编译器如何启用通用约束来消除对显式实现接口的值类型进行装箱的需要.
我想我的问题归结为两部分:
幕后CLR实现发生了什么,需要在访问显式实现的接口成员时将值类型装箱,并且
删除此要求的通用约束会发生什么?
一些示例代码:
internal struct TestStruct : IEquatable<TestStruct>
{
bool IEquatable<TestStruct>.Equals(TestStruct other)
{
return true;
}
}
internal class TesterClass
{
// Methods
public static bool AreEqual<T>(T arg1, T arg2) where T: IEquatable<T>
{
return arg1.Equals(arg2);
}
public static void Run()
{
TestStruct t1 = new TestStruct();
TestStruct t2 = new TestStruct();
Debug.Assert(((IEquatable<TestStruct>) t1).Equals(t2));
Debug.Assert(AreEqual<TestStruct>(t1, t2));
}
}
Run Code Online (Sandbox Code Playgroud)
由此产生的IL:
.class private sequential ansi sealed beforefieldinit TestStruct
extends [mscorlib]System.ValueType
implements [mscorlib]System.IEquatable`1<valuetype TestStruct>
{
.method …Run Code Online (Sandbox Code Playgroud) 我想.IsEmpty()为 ICollection 和 IReadonlyCollection 接口编写一个扩展方法(例如):
public static bool IsEmpty<T>(this IReadOnlyCollection<T> collection)
{
return collection == null || collection.Count == 0;
}
public static bool IsEmpty<T>(this ICollection<T> collection)
{
return collection == null || collection.Count == 0;
}
Run Code Online (Sandbox Code Playgroud)
但是当我将它与实现两个接口的类一起使用时,我显然得到了“模棱两可的调用”。我不想打字myList.IsEmpty<IReadOnlyCollection<myType>>(),我只想打字myList.IsEmpty()。
这可能吗?
鉴于这样的几种类型:
interface I {}
class C : I {}
Run Code Online (Sandbox Code Playgroud)
如何进行静态类型转换?我的意思是:我如何以在编译时检查的方式更改其类型?
在C++中你可以做到static_cast<I*>(c).在C#中,我能做的最好是创建备用类型的临时变量并尝试分配它:
var c = new C();
I i = c; // statically checked
Run Code Online (Sandbox Code Playgroud)
但是这会阻止流畅的编程.我必须创建一个新的变量来进行类型检查.所以我已经确定了这样的事情:
class C : I
{
public I I { get { return this; } }
}
Run Code Online (Sandbox Code Playgroud)
现在我可以静态转换C到我刚好打电话c.I.
在C#中有更好的方法吗?
(如果有人想知道我为什么要这样做,那是因为我使用显式接口实现,并且从另一个成员函数中调用其中一个需要首先转换为接口类型,否则编译器无法找到该方法.)
UPDATE
我想出的另一个选项是对象扩展:
public static class ObjectExtensions
{
[DebuggerStepThrough]
public static T StaticTo<T>(this T o)
{
return o;
}
}
Run Code Online (Sandbox Code Playgroud)
所以((I)c).Doit()也可以c.StaticTo<I>().Doit().嗯...可能仍然坚持简单演员.想想我还是会发布这个其他选项.
c# ×4
.net ×3
.net-4.5 ×1
boxing ×1
generics ×1
icollection ×1
interface ×1
performance ×1
resharper ×1