强制转换和As运算符分别导致强制转换对象和空引用

时间:2019-07-05 03:17:00

标签: c# unity3d casting realproxy as-operator

这个问题几乎完全是出于学习目的。使用的环境是Unity 3D引擎。

我一直在C#中使用RealProxy和MarhalByRefObject类来装饰我的一个类。具体来说,我使用以下构造函数创建了一个通用代理类。我正在装饰的类也具有Seri​​alizableAttribute,并且继承自MarshalByRefObject。

public DynamicProxy(T decorated) : base(typeof(T))
{
} 

要获得装饰的对象,最简单的代码(无装饰)如下

ClassA toDecorate = new ClassA();
DynamicProxy proxy = new DynamicProxy<ClassA>(toDecorate);
Debug.Log(proxy.GetTransparentProxy() as ClassA);
Debug.Log((ClassA)proxy.GetTransparentProxy());    

这是奇怪的地方。我通过反射检查了类型,它的类型确实与我要装饰的对象相同。但是,令人困惑的部分是,当我正常进行转换(ClassA)时,会获得对装饰对象的引用,而当我使用as运算符时,将返回空引用。

当我为Unity v.2019.1.8f1测试我的构建时发现了此行为。脚本运行时版本和我使用的API均与.NET 4.x等效。

如果有人遇到过类似的问题,我想听听他们的看法,因为不应该进行强制转换和操作员行为不同,否则可能会导致大量的时间和精力损失。我并不是真正在寻求解决方案,而是那些可能比我有更好主意或遇到类似问题的人的意见。

注意:如果我只是这样做,就不会发生这种情况

ClassA t = new ClassA();
object o = t;
Debug.Log(o as ClassA);
Debug.Log((ClassA)o);

编辑:经过进一步调查,我注意到as运算符实际上是这样做的

E is T ? (T)(E) : (T)null

发生的是is运算符返回false。

在此处提供代码,以再现问题。

public class HelloThere: MarshalByRefObject
{
    public void DoStuff()
    {
        //Do some stuff here
        Debug.Log("Doing some stuff");
    }
}
public class Proxy<T> : System.Runtime.Remoting.Proxies.RealProxy
{
    private T _decorated;

    public Proxy(T decorated): base(typeof(T))
    {
        _decorated = decorated;
    }

    public override IMessage Invoke(IMessage msg)
    {
        //Do Stuff Before Function
        //Call Function
        var methodCall = msg as IMethodCallMessage;
        var methodInfo = methodCall.MethodBase as System.Reflection.MethodInfo;
        try
        {
            var result = methodInfo.Invoke(_decorated, methodCall.InArgs);
            return new ReturnMessage(
              result, null, 0, methodCall.LogicalCallContext, methodCall);
            //Do Stuff After function
        }
        catch (Exception e)
        {
            return new ReturnMessage(e, methodCall);
        }
    }
}

此外,用于检查每个“广播”返回的代码:

Proxy<HelloThere> proxy = new Proxy<HelloThere>(new HelloThere());
Debug.Log(proxy.GetTransparentProxy() as HelloThere);
Debug.Log((HelloThere)proxy.GetTransparentProxy());

1 个答案:

答案 0 :(得分:0)

该问题似乎源于Unity 3D Engine本身,特别是使用Mono而不是.NET的变体。产生此错误的版本是Unity v.2019.1.8f1。它在Unity 2017.x版本中不存在。正如预期的那样,它也不存在于标准.NET开发的应用程序中。