Операторы Cast и As, приводящие к приведенному объекту и нулевой ссылке соответственно - PullRequest
0 голосов
/ 05 июля 2019

Этот вопрос почти исключительно для учебных целей.В качестве среды используется движок Unity 3D.

Я использовал классы RealProxy и MarhalByRefObject в C # для украшения одного из моих классов.В частности, я создал универсальный прокси-класс, используя конструктор ниже.Класс, который я декорирую, также имеет атрибут SerializableAttribute, наряду с наследованием от 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 голосов
/ 06 июля 2019

Проблема, как представляется, возникла из самого Unity 3D Engine и, в частности, с использованием варианта Mono, а не .NET.Версия, которая породила эту ошибку, - Unity v. 2019.1.8f1.Его не было в версиях Unity 2017.x.Как и ожидалось, его нет в приложении, разработанном в соответствии со стандартом .NET.

...