Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
779 views
in Technique[技术] by (71.8m points)

.net - Accessing a member on Form may cause a runtime exception because it is a field of a marshal-by-reference class

Accessing a member on Form may cause a runtime exception because it is a field of a marshal-by-reference class

I know what this warning is and know how to solve it.

My question is why could this cause a runtime error?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You are probably talking about warning CS1690, repro code:

public class Remotable : MarshalByRefObject {
    public int field;
}
public class Test {
    public static void Run() {
        var obj = new Remotable();
        // Warning CS1690:
        Console.WriteLine(obj.field.ToString());
    }
}

In a remoting scenario, the Test.Run method will work with a proxy of the Remotable object. Building a proxy for a property, method or event isn't much of a problem, just a matter of creating a MethodTable that contains the substitutes. Fields are a problem however, there's nothing to 'hook'. For a MBRO, the JIT compiler no longer generates code to access the field directly, it injects a call to a helper method built into the CLR, JIT_GetField32() in this case.

That helper checks if the object is a proxy and uses the remoting plumbing to obtain the remote value if that's the case. Or just accesses the field directly if it isn't. Making the ToString() call however requires the value to be boxed. That's a problem, boxing isolates the value from the proxy. There is no way to ensure that the boxed value is always an accurate copy of the remoted value. Calling JIT_GetField32() again whenever the ToString() method uses the value to format the string isn't possible.

The workaround for CS1690 is simple, beyond wrapping the field with a property, just copy the field value in a local variable. Now it is crystal clear that the code is working with a copy and there is never a surprise so the compiler won't have to emit a warning.

public static void Run() {
    var obj = new Remotable();
    var value = obj.field;
    Console.WriteLine(value.ToString());     // No warning
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...