我在Enumerable.Single方法中发现(大致)这个代码,同时用一些反编译器检查它:
foreach (TSource current in source)
{
if (predicate(current))
{
result = current;
num += 1L;
}
}
if (num > 1L)
{
throw Error.MoreThanOneMatch();
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,它会在投掷之前循环遍历所有项目.它为什么不打破num > 1?
请参阅代码段
public interface I0
{
void f0();
}
public struct S0:I0
{
void I0.f0()
{
}
}
public class A<E> where E :I0
{
public E e;
public void call()
{
e.f0();
}
}
Run Code Online (Sandbox Code Playgroud)
这是用于调用的IL代码()
.maxstack 8
L_0000: ldarg.0
L_0001: ldflda !0 Temp.A`1<!E>::e
L_0006: constrained !E
L_000c: callvirt instance void Temp.I0::f0()
L_0011: ret
Run Code Online (Sandbox Code Playgroud)
参见约束的参考
约束前缀也可用于在值类型上调用接口方法,因为可以使用MethodImpl更改实现接口方法的值类型方法.如果未使用约束前缀,则强制编译器在编译时选择要绑定到哪个值类型的方法.使用约束前缀允许MSIL在运行时绑定到实现接口方法的方法,而不是在编译时绑定.
这意味着它将调用一个包含接口方法代码f0的方法而不用装箱结构.
在C#中,如上所述GenericClass是否存在任何其他方式没有装箱的caling接口方法?
class A
{
public static explicit operator A(long mm)
{
return null;
}
}
UInt64 ul = UInt64.MaxValue;
IntPtr ptr = (IntPtr)ul;//no error
A a = (A)ul;//Cannot convert type 'ulong' to 'A'
Run Code Online (Sandbox Code Playgroud)
为什么IntPtr允许这种行为?
以下是IL代码:
.entrypoint
.maxstack 1
.locals init (
[0] uint64 ul,
[1] native int ptr)
L_0000: nop
L_0001: ldc.i4.m1
L_0002: conv.i8
L_0003: stloc.0
L_0004: ldloc.0
L_0005: call native int [mscorlib]System.IntPtr::op_Explicit(int64)
L_000a: stloc.1
L_000b: ret
Run Code Online (Sandbox Code Playgroud) 在x86上,如果mem是32位对齐的,则mov操作保证是原子的.
如果[mem]不是32位对齐,那么lock inc [mem]sill工作正常吗?
工作正常:提供原子性而不是获得部分价值.
GroupJoin方法在关系数据库术语中没有直接等价,但它实现了内连接和左外连接的超集.左外连接是返回第一个(左)数据源的每个元素的连接,即使它在其他数据源中没有相关元素也是如此.
我认为GroupJoin相当于左连接.因为外部的所有元素都将返回内部匹配项的集合.如果在inner中找不到匹配的项,则空集合将与外部元素配对.
但为什么msdn会这么说呢?
我已阅读GroupJoin和Join的源代码.MarcinJuraszek提供了一个例子.但我认为我们可以使用以下代码.
Users.GroupJoin(Cars,user=>id,Car=>userId,(user,cars)=>
if(cars.count==0)
{
//John -- NULL
}
else
{
//Ted -- [ 2, 3 ]
}
return result;
);
Run Code Online (Sandbox Code Playgroud)
GroupJoin的原始逻辑:
Lookup<TKey, TInner> lookup = Lookup<TKey, TInner>.CreateForJoin(inner, innerKeySelector, comparer);
foreach (TOuter current in outer)
{
yield return resultSelector(current, lookup[outerKeySelector(current)]);
}
Run Code Online (Sandbox Code Playgroud)
我们也可以重写一个LeftJoin:
Lookup<TKey, TInner> lookup = Lookup<TKey, TInner>.CreateForJoin(inner, innerKeySelector,
foreach (TOuter current in outer)
{
yield return resultSelector(current, lookup[outerKeySelector(current)].DefaultIfEmpty());
}
Run Code Online (Sandbox Code Playgroud) 如果使用Visual Studio 2010编译以下代码:
public struct A
{
public static implicit operator B(A a)
{
Console.WriteLine("11111111111");
return new B();
}
}
public struct B
{ }
public static B F(A? a)
{
return (B)a;
}
Run Code Online (Sandbox Code Playgroud)
使用ILSpy,return (B)a;实际编译为return A.op_Implicit(a.value).
根据我对C#4.0第6.4.5节"用户定义的显式转换"的理解,它应该产生编译器错误.
但是,阅读ECMA 334第13.4.4节"用户定义的显式转换",它有一个不同的规则,上面的代码似乎符合这一规则.
C#4.0:
查找适用的用户定义和提升转换运算符集合U.此集合包含由 D中的类或结构声明的用户定义和提升的隐式或显式转换运算符,这些运算符从包含或包含在S中的类型转换为T包含或包含T.如果U为空,则转换未定义,并发生编译时错误.
ECMA 334:
找到适用的转换运算符集合U.这个集合包含用户定义的,如果S和T都可以为空,则提升隐式或显式转换运算符(第13.7.3节),由转换为D的类或结构声明从包含或包含在S中的类型到包含或包含在T中的类型.如果U为空,则不存在转换,并且发生编译时错误.
我是否认为VS2010不符合C#4.0规范中的"用户定义的转换评估"部分,但是是否符合ECMA规范?
在msdn http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208(v=vs.85).aspx上,MemoryBarrier是作为对xchg的调用来实现的。
// x86
FORCEINLINE
VOID
MemoryBarrier (
VOID
)
{
LONG Barrier;
__asm {
xchg Barrier, eax
}
}
Run Code Online (Sandbox Code Playgroud)
我在“软件开发人员手册”中找不到一些材料。请告诉我原因。
int i=9999;
char c=i;
Run Code Online (Sandbox Code Playgroud)
没有溢出警告,而
char c=9999;
Run Code Online (Sandbox Code Playgroud)
给,
警告C4305初始化从int到char的截断
为什么没有溢出转换时警告int到char?