是否可以在没有Visual Studios调试模式的情况下自动打印NullReferenceException中为null的变量?

Is it possible to automate printing the variable which is null in a NullReferenceException without Visual Studios debugging mode?

提问人:seppel 提问时间:9/3/2022 最后编辑:seppel 更新时间:9/6/2022 访问量:70

问:

假设我有一个包含大量成员和嵌套成员的类,并执行此调用,并且其中一个变量为 null(除了等式两边的最后一个变量):

Obj.Field.NextField.NextNextField = NextObj.OtherField.NextOtherField.NextNextOtherField;

我将得到一个 NullReferenceException,指出此行中的对象为 null。 在这种情况下,有 6 种不同的情况可能源于异常。

我现在经常遇到这种情况,并且总是执行以下操作来找出哪个成员实际上是空的。

public static void PrintNullOrigin(params object[] _args)
    {
        for (int i = 0; i < _args.Length; i++)
        {
            if (_args[i] == null)
            {
                print(_args[i] + " is null!");
            }
        }
    }

但在这种情况下,你仍然必须这样做:

PrintNullOrigin(Obj, NextObj, Obj?.Field, NextObj?.OtherField, ...);

有没有办法在每次抛出 NullReferenceException 时,记录器都会自动执行此操作?

我尝试通过Exception对象获取NullReferenceException源自的行中的成员,但是我找不到任何使它变得容易的东西。

编辑:

我必须在这里强调,我想知道是否可以在Visual Studios调试模式之外进行此操作。

在 Unity 中,Visual Studio 的调试模式应很少使用,因为运行时可能会发生崩溃和性能损失。

C# .NET 调试 NullReferenceException

评论

1赞 Slack Groverglow 9/3/2022
相反,我会熟悉 Visual Studio 调试功能 learn.microsoft.com/en-us/visualstudio/debugger/......
0赞 Etienne de Martel 9/6/2022
我只需打开可为空的引用并在编译时发现这些问题。

答:

0赞 Michael Kokorin 9/5/2022 #1

访问字段时,无法打印哪个字段为空。在访问该字段之前,您仍然需要进行一些检查。 此检查可以通过多种方式进行:

  1. 你可以使用一些函数,如 CheckForNull(NextObj, “NextObj.OtherField.NextOtherField.NextNextOtherField”),然后通过拆分第二个参数并使用 Reflection - 你可以调查此路径中的哪些字段为 null
  2. 这种方式稍微复杂一些:第二个参数的类型可以类似于 Expression<Func<NextObj, T>> 和 value as obj => NextObj.OtherField.NextOtherField.NextNextOtherField。因此,您将拥有此映射的表达式,并且可以通过检查此表达式树来查找哪些字段为 null。

但总的来说,如果你有这样的东西:“NextObj.OtherField.NextOtherField.NextNextOtherField” 这是一个不好的迹象 - 因为当你必须这样做时,它是架构不佳的应用程序。

评论

0赞 seppel 9/5/2022
解释第一句话。
0赞 Michael Kokorin 9/6/2022 #2

你可以做这样的事情:

var propertiesTree = "NextObj.OtherField.NextOtherField.NextNextOtherField".Split('.');
object obj = NextObj;
for(var index = 1; index < propertiesTree.Length; index++)
{
    var property = obj.GetType().GetProperty(propertiesTree[index]);
    var value = property.GetValue(obj);
    if (value == null) { throw new Exception($"{propertiesTree[index]} is null"); }
    obj = value;
}

// if we are here - then all fields are not null