用.NET语言编写的所有代码都编译为MSIL,但是只有使用MSIL才能直接执行特定的任务/操作吗?
让我们在MSIL中比C#,VB.NET,F#,j#或任何其他.NET语言更容易完成.
到目前为止我们有这个:
raise元素定义事件.main()方法作为.entrypoint.int和本机unsigned int类型.protected internal是fam 或 assem)<Module>类以定义全局函数或模块初始值设定项.调查一个bug,我发现这是由于c#中的这种奇怪:
sbyte[] foo = new sbyte[10];
object bar = foo;
Console.WriteLine("{0} {1} {2} {3}",
foo is sbyte[], foo is byte[], bar is sbyte[], bar is byte[]);
Run Code Online (Sandbox Code Playgroud)
输出为"True False True True",而我希望" bar is byte[]"返回False.显然酒吧既是一个byte[]又是一个sbyte[]?同样的情况对于其他符号/无符号类型,如Int32[]VS UInt32[],但不是说Int32[]VS Int64[].
谁能解释这种行为?这是在.NET 3.5中.
我得到了System.ArrayTypeMismatchException: Source array type cannot be assigned to destination array type此代码段的异常:
var uints = GetArray();
if (uints is int[])
{
var list = ((int[])uints).ToList(); // fails when call ToList()
}
private Array GetArray()
{
var result = new uint[] { uint.MaxValue, 2, 3, 4, 5 };
return result;
}
Run Code Online (Sandbox Code Playgroud)
然后我求助于Jon的回答为什么在C#中"int []是uint [] == true",它告诉我,由于GetArray()返回a Array,转换在运行时被推迟,而CLR允许这种转换int[] to uint[](vice versa).如果我在转换后检查值,它实际上工作正常:
foreach (var i in ((int[])units))
{
System.Console.WriteLine(i.GetType());
System.Console.WriteLine(i);
}
Run Code Online (Sandbox Code Playgroud)
我会得到:
System.Int32
-1
System.Int32 …Run Code Online (Sandbox Code Playgroud) 考虑以下枚举声明和int数组:
enum Test { None };
int[] data = {0};
Run Code Online (Sandbox Code Playgroud)
要将此int[]数组转换为Test[]数组,我们可以简单地执行此操作:
Test[] result = Array.ConvertAll(data, element => (Test)element);
Run Code Online (Sandbox Code Playgroud)
我最初试图这样做:
Test[] result = data.Cast<Test>().ToArray();
Run Code Online (Sandbox Code Playgroud)
但是,它会在运行时抛出异常:
System.ArrayTypeMismatchException:无法将源数组类型分配给目标数组类型.
问题一
有没有办法使用Linq并Cast<>没有错误,或者我必须使用Array.Convert()?
问题二(在第一个问题得到正确回答后添加)
究竟为什么不起作用?
看起来这是一个实现细节逃逸的情况......考虑:
这会导致错误:
var result = data.Cast<Test>().ToList(); // Happens with "ToList()" too.
Run Code Online (Sandbox Code Playgroud)
但这不是:
var result = new List<Test>();
foreach (var item in data.Cast<Test>())
result.Add(item);
Run Code Online (Sandbox Code Playgroud)
这也不是:
var result = data.Select(x => x).Cast<Test>().ToList();
Run Code Online (Sandbox Code Playgroud)
明确的含义是在.ToList()实现中正在进行某种优化,导致此异常.
附录:
这也有效:
List<int> data = new List<int>{0};
var result …Run Code Online (Sandbox Code Playgroud) 注意:这不是"使用IsAssignableFrom和"是"C#中的关键字"的副本.另一个问题是
typeof(T).IsAssignableFrom(type)),哪里type不是一个object而是一个Type.这似乎微不足道 - 我可以听到你说,"只要打电话
x.GetType()!" - 但是由于下面提到的与COM相关的角落情况,该调用会导致问题,这就是我要求重写的原因.
......还是有罕见的特殊情况,两者可能会给出不同的结果?
我偶然发现了一张表格的类型检查:
typeof(TValue).IsAssignableFrom(value.GetType())
Run Code Online (Sandbox Code Playgroud)
where TValue是泛型类型参数(没有任何约束)并且value是object.
我不完全确定将上述内容重写为以下是否安全:
value is TValue
Run Code Online (Sandbox Code Playgroud)
据我所知,这两个测试是相同的,但COM对象除外.is应该触发一个正确的QueryInterface,同时IsAssignableFrom可能会被__ComObjectRCW包装类型混淆并报告错误否定.
是否有任何其他差异is和显示的使用IsAssignableFrom?
我有一些代码,它采用一个值(类型为object)并尝试将其转换为IEnumerable的int和uint,如下所示:
var idList = value as IEnumerable<int>;
var uintList = value as IEnumerable<uint>;
Run Code Online (Sandbox Code Playgroud)
以这种方式初始化值时:
uint number = 1;
object value = new []{ number };
Run Code Online (Sandbox Code Playgroud)
idList和uintList都有值,但调用idList.ToList()会产生一个ArrayTypeMismatchException.但是,当生成值时new List<uint>{ number },idList按预期为null.
此外,var idList = value as IEnumerable<int>;即使使用集合初始值设定项生成值,在VS 2015中调用即时窗口也会返回null,就像我预期的那样.
这里发生了什么?
有人可以解释为什么会这样吗?
var y = new int[]{1,2};
Console.WriteLine(y is uint[]); // false
Console.WriteLine(((object)y) is uint[]); // true
Run Code Online (Sandbox Code Playgroud) 这是我认为昨天解决的一个帖子的后续内容.昨天我在以下情况下遇到了我的代码问题:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Program
{
class Bar
{
int v;
public Bar(int v) { this.v = v; }
public override string ToString() { return v.ToString(); }
}
static void Main(string[] args)
{
Foo(1, 2, 3);
Foo(new int[] { 1, 2, 3 });
Foo(new Bar(1), new Bar(2), new Bar(3));
Foo(new Bar[] { new Bar(1), new Bar(2), new Bar(3) });
System.Threading.Thread.Sleep(20000);
}
static void Foo(params object[] objs)
{
Console.WriteLine("New call …Run Code Online (Sandbox Code Playgroud) c# ×8
.net ×3
types ×2
arrays ×1
c#-5.0 ×1
casting ×1
cil ×1
clr ×1
ienumerable ×1
linq ×1
params ×1
reflection ×1
system.type ×1