编辑:This explains everything! - 当您销毁它们时,Unity会在UnityEngine.Objects周围创建托管假包装器。这意味着如果您销毁UEObject,C#包装器仍可能不为空。 ==以自定义方式实现,以便在销毁UEObject时检查== null将返回true。这显然不适用于泛型。
这实际上让我疯了。我有这个方法:
public static void AssertNotNullAfterAssignment<T>(ref T value, Func<T> get, string msg) where T : class
{
if (value == null)
value = get();
if (value == null)
throw new NullReferenceException(msg);
}
我在一个开头为null的引用上调用它:
AssertNotNullAfterAssignment(ref fovMeshFilter, GetComponent<MeshFilter>, "fovMeshFilter");
真正疯狂的是,支票if (value == null)
正在返回假!即使值为空!
Here's a short video我做了这个。
有趣的是,如果我将方法代码复制/粘贴到我在其中使用的方法(在OnEnable中)它可以工作(几乎我在视频中的OnEnable中评论过)
所以...如果它在断言方法之外,它可以工作,但不在内部。我也尝试了Equals
而不是==
,但也是如此。
任何人都知道发生了什么事?
编辑:这是OnEnable,我正在调用断言的方法:
private void OnEnable()
{
//if (fovMeshFilter== null)
// fovMeshFilter= GetComponent<MeshFilter>();
//if (fovMeshFilter== null)
// throw new NullReferenceException("fovMeshFilter");
AssertNotNullAfterAssignment(ref fovMeshFilter, GetComponent<MeshFilter>, "fovMeshFilter");
}
如果我使用未注释的行,它按预期工作,但断言方法不适用于某些只有上帝知道的原因。
Edit1:我们在这里有什么?
EDIT2:
EDIT3:
因此,在这个令人敬畏的社区的大力帮助下,以及几个测试后我找到了解决方案。 我可以发誓这是我尝试过的第一件事!你必须相信我! XD - 只是使用.Equals
而不是==
- 就像@Edin在他的回答中所显示的那样,对通用对象执行==
似乎调用{{1} } System.Object
- 但是,调用==
应始终解析为.Equals
的正确重载。我不知道为什么会这样,我的意思是,为什么“==”也不能解决正确的过载问题?
答案 0 :(得分:4)
您的对象不为空。在调试器中查看null
并不意味着它是一个空引用。如果您可以在调试器中展开对象,那么它肯定不是空引用。可能是DebuggerDisplay
字符串或ToString()
方法在您的情况下返回"null"
,但这与空引用不同。
举一个这个类的例子
[DebuggerDisplay("null")]
class A { }
a
A
var a = new A();
当你用鼠标在它上面运行时,将在调试器中显示为a|null
。
您的T
肯定有此属性。 ToString()
覆盖返回"null"
会在字符串周围添加额外的花括号:a|{null}
。
修改强>
看到你的Edit2,让我意识到你的真正问题可能是什么。您的==
运算符很可能被覆盖,因此在您将类的实例与null进行比较时,它会返回true,尽管实例本身不为null。但是,在通用方法中,不知道参数在编译时的类型,因此最常用的运算符将应用于T
参数,即参考比较。这在以下主题中有详细描述:C# generics class operators not working
这可能是OnEnable()
中的comparioson工作的原因,而且你的泛型方法中的比较没有。
然而,这还没有完全证明,因为我看不到你的代码。但你可以验证一下。
以下是运算符与泛型无法正常工作的完整工作示例:
class Person
{
public string Name { get; set; }
public static bool operator ==(Person left, Person right)
{
// we consider Person null when it either has no Name or it is a null reference.
if (object.ReferenceEquals(null, left) || left.Name == null)
return object.ReferenceEquals(null, right);
return left.Equals(right);
}
public static bool operator !=(Person left, Person right) { return !(left == right); }
// Note that == and != operators should ideally be implemented in combination of Equals() override.
// This is only for making an example for this question
}
private static bool IsNull<T>(T val)
{
return val == null;
}
static void Main(string[] args)
{
Person person = new Person();
//this will display: person == null => True
Console.WriteLine("person == null => {0}", person == null);
//this will display: IsNull<Person>(person)=> False
Console.WriteLine("IsNull<Person>(person)=> {0}", IsNull(person));
}
答案 1 :(得分:3)
vexe,在你的视频中,当你将鼠标移到值上时,你会看到它为空,但你也看到它左边有一个小三角形,好像你可以展开它一样。你尝试过扩展吗?因为当鼠标覆盖null本身时你没有得到那个三角形。也许它不是null,而是它的一个对象,.toString()
返回null。
修改强>
我认为你的对象不是null。并且您的调试器未能向您显示正确的值。 (因此屏幕截图中有例外。)
尝试在被调用的函数中执行类似var foo = value.mesh;
的操作,然后在该函数上进行调试。
似乎这个对象不是那么断点/观看友好。