C# 在C中用另一个对象实例替换对象实例#
在这个问题上,我想知道这是否以及如何可能。这种技术看起来非常糟糕,但我正在使用的API(UnityEdit)似乎正在做类似的事情,我只是好奇 如果对同一对象有多个引用,是否可以将新对象实例化到同一内存插槽中,以便所有以前的引用都指向新对象 我发现唯一可行的方法是使用非托管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
// 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
)属性。如果它是要引用的自定义类,我认为可以让所有引用指向伪引用
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)
?@dtryonprefableUtility.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();
}
}