C# 在C中用另一个对象实例替换对象实例#

C# 在C中用另一个对象实例替换对象实例#,c#,memory,pointers,reference,unity3d,C#,Memory,Pointers,Reference,Unity3d,在这个问题上,我想知道这是否以及如何可能。这种技术看起来非常糟糕,但我正在使用的API(UnityEdit)似乎正在做类似的事情,我只是好奇 如果对同一对象有多个引用,是否可以将新对象实例化到同一内存插槽中,以便所有以前的引用都指向新对象 我发现唯一可行的方法是使用非托管C++。基本上发生了以下情况: // Original prefab GameObject prefab = x; prefab.tag = "Untagged"; // A copy of the original pref

在这个问题上,我想知道这是否以及如何可能。这种技术看起来非常糟糕,但我正在使用的API(UnityEdit)似乎正在做类似的事情,我只是好奇

如果对同一对象有多个引用,是否可以将新对象实例化到同一内存插槽中,以便所有以前的引用都指向新对象

我发现唯一可行的方法是使用非托管C++。基本上发生了以下情况:

// Original prefab
GameObject prefab = x;
prefab.tag = "Untagged";

// A copy of the original prefab
GameObject prefabCopy = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
prefabCopy.tag = "EditorOnly";  // Change from initial value "Untagged"

Debug.Log(prefab.tag);     // "Untagged"   - expected
Debug.Log(prefabCopy.tag); // "EditorOnly" - expected

// Replace contents of prefab file with `prefabCopy`
PrefabUtility.ReplacePrefab(prefabCopy, prefab);

// Destroy the copy
DestroyImmediate(prefabCopy);

Debug.Log(prefab.tag);     // "EditorOnly"   - whoa?
一些
prefate
现在如何指向不同的对象


注意:请记住,Unity是建立在.NET的单一风格之上的。不,这是不可能的

要实际更改对对象的所有引用,必须冻结进程中的所有线程,并访问它们的寄存器集和堆栈。这就是垃圾收集器所做的,但对于常规代码来说是不可能的


该方法最有可能做的是将一个对象的深度复制到另一个对象上。

由于对象状态由字段值定义,因此可以将包含字段值的内存从一个对象复制到另一个对象,有效地“替换”它:

公共静态无效替换(tx,ty)
T:在哪里上课
{
//将“x”替换为“y”
如果(x==null)抛出新的ArgumentNullException(“x”);
如果(y==null)抛出新的ArgumentNullException(“y”);
var size=Marshal.SizeOf(typeof(T));
var ptr=Marshal.AllocHGlobal(大小);
Marshal.StructureToPtr(y,ptr,false);
结构(ptr,x);
弗里赫全球元帅(ptr);
}

请注意,此代码需要为类定义
[StructLayout(LayoutKind.Sequential)]
(或
LayoutKind.Explicit
)属性。

如果它是要引用的自定义类,我认为可以让所有引用指向伪引用

  • 创建你的类(A)
  • 创建类接口(IA)
  • 基于接口创建一个包装器类,该类只将所有调用传递给包含的对象(AC)
  • 我添加了一个赋值运算符,因此我将所有对象都作为ACs

    class AC:IA  
    {  
        IA ref;  
        AC(IA ref)  
        {  
            this.ref = ref;  
        }  
    
        public void ChangeReference(IA newRef) { ref = newRef;}  
        public static operator = (IA assignedObj)  
        {  
            return (assignedObject is AC) ? assignedObject : new AC(assignedObj);
        }
    
        // implementation of all methods in A
        public override string ToString() { return ref.ToString(); }  
            ...  
    }
    
    现在,如果需要,可以使用ChangeReference方法将所有内容切换到新引用

    C++中使用引用引用< /P>
    祝您好运

    如果您将对象嵌入到另一个用于访问该对象的对象中,您可以做到这一点

    class ObjectReference<T>
       where T : new()
    {
        private T _obj = new T();
    
        public void CreateNewObject()
        {
            _obj = new T();
        }
    
        public T Value { get return _obj; }
    }
    

    现在可以像使用“真实”对象一样使用包装器。您还可以在包装器的构造函数中传递“real”对象的初始实例,并删除
    \u obj

    的初始值设定项
    prefableUtility.replacePrefable(prefableCopy,prefable)
    ?@dtryon
    prefableUtility.replacePrefable
    调用内部方法(根据程序集浏览器)。我认为这是最可能的情况。虽然我相信UnityEngine.Object不是线程安全的,但事实并非如此,他是对的。事实上,我相信文档明确指出它是在复制,而不是传递引用。
    UnityEngine.Object
    具有
    [StructLayout(LayoutKind.Sequential)]
    Unity重载所有相等运算符,这些运算符在销毁后会执行异常操作,例如将正值与
    null
    进行比较。使用
    封送
    是否有方法显示指针的字符串表示形式?我想将
    prefact
    的引用与
    prefableUtility.replacePrefact
    的返回值进行比较,但Unity无法执行任何类型的黑魔法。您可以使用
    var gch=GCHandle.Alloc(obj,GCHandleType.pinted)获取某些对象的地址;var address=gch.addrofpindedObject();gch.Free()
    ,但它不适用于大多数对象类型。我认为这是尽可能接近对象地址的。无论如何,我不认为有什么东西会改变代码中的引用而不是对象实例(当然,垃圾收集器除外)。我希望推断更新的预制引用是否与原始引用相同,因为这意味着对象正在被重用。不幸的是,这不适用于此对象类型
    ArgumentException:对象包含非基本数据或非blittable数据。
    Cheers:-)我接受了这个答案,因为我认为这是最有可能的,特别是考虑到存在
    StructLayout
    属性。如果您的类将属性设置为另一个对象(例如MyProperty=SomeOtherInstancedObject)。现在,如果修改了MyProperty,为什么我看不到其他实例化对象中的更改?你会怎么做?Thanks@toughQuestions:当
    MyProperty
    包含对
    SomeOtherInstancedObject
    的引用,并且您修改
    MyProperty
    本身时,它将指向另一个对象或
    null
    ,但它不会修改
    SomeOtherInstancedObject
    。但是如果修改
    MyProperty.SomeProperty
    ,则会更改
    someotherinstancedObject
    中的属性。您必须知道类是引用类型。此类类型的变量始终包含引用或
    null
    。另请参阅我对的回答。感谢链接,它非常清楚:-)那么,我该如何解决我的问题呢?是直接使用其他实例化对象的唯一方法,因为没有真正的方法将其“重命名”为MyProperty?请向SO发帖,展示相关代码并详细解释问题。从这些简短的评论中,我们很难理解您的问题。
    class ObjectReference<T>
       where T : new()
    {
        private T _obj = new T();
    
        public void CreateNewObject()
        {
            _obj = new T();
        }
    
        public T Value { get return _obj; }
    }
    
    interface ISomeInterface
    {
        string PropertyA { get; set }
        void MethodB (int x);
    }
    
    class TheRealObject : ISomeInterface
    {
        public string PropertyA { get; set }
    
        public void MethodB (int x)
        {
            Console.WriteLine(x);
        }
    }
    
    class Wrapper : ISomeInterface
    {
        TheRealObject _obj = new TheRealObject();
    
        public string PropertyA
        { 
            get { return _obj.PropertyA; }
            set { _obj.PropertyA = value; }
        }
    
        public void MethodB (int x)
        {
            _obj.MethodB(x);
        }
    
        public void CreateNewObject()
        {
            _obj = new TheRealObject();
        }
    }