值为null,但是否则返回检查?

时间:2014-06-02 13:17:20

标签: c# debugging null unity3d

编辑: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:我们在这里有什么?

enter image description here

EDIT2:

enter image description here

EDIT3:

因此,在这个令人敬畏的社区的大力帮助下,以及几个测试后我找到了解决方案。 我可以发誓这是我尝试过的第一件事!你必须相信我! XD - 只是使用.Equals而不是== - 就像@Edin在他的回答中所显示的那样,对通用对象执行==似乎调用{{1} } System.Object - 但是,调用==应始终解析为.Equals的正确重载。我不知道为什么会这样,我的意思是,为什么“==”也不能解决正确的过载问题?

2 个答案:

答案 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;的操作,然后在该函数上进行调试。

似乎这个对象不是那么断点/观看友好。