C# 在不同编译下的不同表现
这是我在2018年的时候发在Unity Forums上的帖子, 至今无人回复, 之前是想用TypedReference做DataTable的相关功能的, 可是结果不正确.
System.TypedReference bugged? can't figure out how to use it !!!
C# has some way to get Generic Type target pointer, such as GCHandle / Marshal, this time I want to use System.TypedReference for getting pointer of any struct, bug I think it's bugged... I dont know how to report a BUG to Unity, just post it here here is the code, it works in VS project but not unity project:
void Start() { int v1 = 100; int v2 = 1000; var m1 = __makeref(v1); var m2 = __makeref(v2); var val1 = __refvalue(m1, int); // val1 is 100 var val2 = __refvalue(m2, int); // val2 is 1000 Debug.Log(val1); Debug.Log(val2); unsafe { *(IntPtr*)(&m1) = new IntPtr((void*)&v2); // 这里应该是把m1的值改变了的 m1应该为1000 val1 = __refvalue(m1, int); // val1 is 100 -- not changed 可是这里m1赋值没有变换, 还是100 val2 = __refvalue(m2, int); // val2 is 1000 Debug.Log(val1); Debug.Log(val2); var ptr = *(IntPtr*)(&m1); var p = (int*)ptr.ToPointer(); var data = *p; // data is 1000 -- changed 奇怪的是这里得到的m1的值又是1000 Debug.Log(data); } }
And what's more, if I dont Set the pointer of m1, the value of [data] is Strange!!
void Start() { int v1 = 100; int v2 = 1000; var m1 = __makeref(v1); var m2 = __makeref(v2); var val1 = __refvalue(m1, int); // val1 is 100 var val2 = __refvalue(m2, int); // val1 is 1000 Debug.Log(val1); Debug.Log(val2); unsafe { var ptr = *(IntPtr*)(&m1); var p = (int*)ptr.ToPointer(); var data = *p; // data is 536019728 [random] -- WTF 更奇怪的是直接取m1的值, 居然不对 Debug.Log(data); } }
This issue is happened in unity project, it works as expected in VS project.
the VS project value is :
static unsafe void TT() { int v1 = 100; int v2 = 1000; var m1 = __makeref(v1); var m2 = __makeref(v2); var val1 = __refvalue(m1, int); // val1 is 100 var val2 = __refvalue(m2, int); // val2 is 1000 unsafe { *(IntPtr*)(&m1) = new IntPtr((void*)&v2); // m1值被赋值1000 val1 = __refvalue(m1, int); // val1 is 1000 VS工程编译的话, 这个m1值赋值正确的 1000 val2 = __refvalue(m2, int); // val2 is 1000 var ptr = *(IntPtr*)(&m1); var p = (int*)ptr.ToPointer(); var data = *p; // data is 1000 这里也是正确的 } }
这个也是偶然想到极限速度对变量赋值的时候看到的做法, 测试以后发现不对劲. 以前大部分时候程序出错我们都会先想到是自己代码写错了, 不过这里可以看出
编译器也是有错的时候的......
===============================
又碰到一个, 版本为Unity2019了, 使用 Task 的 Wait() 方法会造成卡死...
[MenuItem("Test/RunUpdate")] public async static void TestRun() { try { Run().Wait(); // 必须使用 await Run(); } catch(Exception ex) { Debug.LogError(ex.Message); } } private static async Task Run() { System.IO.FileStream fs = new System.IO.FileStream(@"C:\Users\xxxx\Desktop\Test\test.txt", System.IO.FileMode.Create); string str = @"Hello World!!!"; var buffer = System.Text.Encoding.UTF8.GetBytes(str); await fs.WriteAsync(buffer, 0, buffer.Length); Debug.Log("End"); }