我试图弄清楚为什么以下代码抛出StackOverflowException(我终于在SO中发布了StackoverflowException!).
调试似乎指出p.GetValue(this)正在生成进一步的调用.
究竟是什么触发了无限的调用链?是因为p.GetValue(this)最终返回当前对象的一个实例,因此就像构造一个新实例一样(并且在其构造中构造自身的每个对象都会导致Stackoverflow异常)?
我对以下代码的意图是让一个对象能够告诉它有多少属性具有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 StackOverflowException (the construction line itself) A a1 = new A1{ S1 = "aaa"}; Console.WriteLine(a1.NonInitializedFields);
PS我的想法最初只涉及简单的字符串属性,没有别的,所以这种方法与其他类型可能出现的问题无关紧要.
您有一个属性,当您执行"get"访问器时,它会查找所有属性并获取它们的值.所以它以递归方式执行.
如果您只需要字符串属性,则应在获取值之前检查属性类型:
var properties = GetType().GetProperties().Where(p => p.PropertyType == typeof(string));
此时,由于您的NonInitializedFields
属性没有返回类型string
,因此不会执行.
我个人认为,无论如何,我会把它变成一个方法调用而不是一个属性,请注意.这也将解决问题,因为该方法在寻找属性时不会发现自己.
我也会将其重命名为:
属性不一定由字段支持
可以将字段显式初始化为null
对仅包含空格的字符串的引用
GetNonWhitespaceStringPropertyCount()
IMO 称,一种方法更准确.您还可以使整个实现成为LINQ查询:
return GetType().GetProperties() .Where(p => p.PropertyType == typeof(string)) .Select(p => p.GetValue(this)) .Count(v => !string.IsNullOrWhitespace((string) v));
请注意,我已经修复了代码中的下一个问题 - 您的意思是计算非null /空值,但实际上是在计算null/empty值.