这个对象能够告诉它有多少属性不是 null/whitespace/empty 有什么问题?

What is wrong with this object being capable of telling how many of its properties are not null/whitespace/empty?

我想弄清楚为什么以下代码会抛出 WhosebugException(我终于在 SO 中发布了 WhosebugException!)。

调试似乎指出 p.GetValue(this) 正在生成更多调用。

实际上是什么触发了无限调用链?是因为 p.GetValue(this) 最终 returns 当前对象的一个​​实例,因此就像构造一个新实例一样(并且在其构造中构造自身的每个对象都会导致 Whosebug 异常)?

我对以下代码的意图是让一个对象能够告诉它有多少属性具有 null/space/empty 值。

public class A
{
    public string S1 { get; set; }
    public string S2 { get; set; }

    public int NonInitializedFields
    {
        get
        {
            int nonNullFields = 0;

            var properties = this.GetType().GetProperties();
            foreach (var p in properties)
            {
                var value = p.GetValue(this);
                if (value == null || string.IsNullOrWhiteSpace(value.ToString()))
                    nonNullFields++;
            }

            return nonNullFields;
        }
    }
}

//the following throws a WhosebugException (the construction line itself)
A a1 = new A1{ S1 = "aaa"};
Console.WriteLine(a1.NonInitializedFields);

P.S。我的想法本来只涉及简单的字符串属性,没有别的,所以这种方法与其他类型可能出现的问题无关。

您有一个 属性,当您执行 "get" 访问器时,它会找到所有 属性 并获取它们的值。所以它会递归地执行自己。

如果您只需要字符串属性,您应该在 获取值之前检查 属性 类型

var properties = GetType().GetProperties().Where(p => p.PropertyType == typeof(string));

此时,由于您的NonInitializedFields 属性 没有return 类型的string,它不会被执行。

请注意,就我个人而言,无论如何,我会将其设为方法调用而不是 属性。这也可以解决问题,因为该方法在查找属性时不会找到自己。

我也将其重命名为:

  • A 属性 不一定由字段支持
  • 字段可以显式初始化为 null 或对仅包含空格的字符串的引用

IMO,一种叫做 GetNonWhitespaceStringPropertyCount() 的方法会更准确。您还可以使整个实现成为 LINQ 查询:

return GetType().GetProperties()
                .Where(p => p.PropertyType == typeof(string))
                .Select(p => p.GetValue(this))
                .Count(v => !string.IsNullOrWhitespace((string) v));

请注意,我已经解决了您代码中的下一个问题 - 您本应计算 non-null/empty 个值,但实际上您计算的是 null/empty个。