在这个问题中,我想知道是否以及如何做到这一点。这种技术似乎是非常糟糕的做法,但似乎我正在使用的API(UnityEditor)正在做这样的事情,我只是很好奇。
如果对同一个对象有多个引用,是否可以将新对象实例化到同一个内存槽中,以便所有先前的引用都指向新对象?
我发现唯一可行的方法是使用非托管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?
prefab
现在如何指向不同的对象?
注意:请记住Unity是基于.NET的Mono风格构建的
答案 0 :(得分:5)
由于对象状态是由字段值定义的,因此您可以将包含字段值的内存从一个对象复制到另一个对象,从而有效地“替换”它:
public static void Replace<T>(T x, T y)
where T : class
{
// replaces 'x' with 'y'
if(x == null) throw new ArgumentNullException("x");
if(y == null) throw new ArgumentNullException("y");
var size = Marshal.SizeOf(typeof(T));
var ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(y, ptr, false);
Marshal.PtrToStructure(ptr, x);
Marshal.FreeHGlobal(ptr);
}
请注意,此代码需要为类定义[StructLayout(LayoutKind.Sequential)]
(或LayoutKind.Explicit
)属性。
答案 1 :(得分:5)
如果将对象嵌入到用于访问对象的另一个对象中,则可以这样做。
class ObjectReference<T>
where T : new()
{
private T _obj = new T();
public void CreateNewObject()
{
_obj = new T();
}
public T Value { get return _obj; }
}
现在,您可以创建对MyObjectReference
类型的对象的多个引用,并且只更改本地对象。可以通过Value
属性
一种稍微不同的方法是创建一个与“真实”对象实现相同接口的包装器,从而使这种包装透明。
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();
}
}
现在包装器可以像使用“真实”对象一样使用。您还可以在包装器的构造函数中传递“真实”对象的初始实例,并删除_obj
的初始化器。
答案 2 :(得分:3)
不,那是不可能的。
要实际更改对象的所有引用,您必须冻结进程中的所有线程,并访问其寄存器集和堆栈。这就是垃圾收集器的作用,但是常规代码不可能。
最有可能的方法是将一个对象的深层副本复制到另一个对象上。
答案 3 :(得分:1)
如果它是您要引用的自定义类,我认为您可以将所有引用指向假冒参考...
我添加了一个Assignment运算符,所以我将所有A对象都作为AC。
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方法将所有内容切换到新的Reference ..
在C ++中,您将使用Reference to Reference
祝你好运