带有select子句的System.NullReferenceException
本文关键字:System NullReferenceException 子句 select 带有 | 更新日期: 2023-09-27 18:25:46
大家好,亲爱的社区:D
现在我正在做我的第一个大项目,有点停滞不前。我正在尝试验证一些输入。
因此我使用这个功能:
public static Validatable<string> RequiredOr(this Validatable<string> that, Func<Validatable<string>, bool> func)
{
return that.DoEvaluate && !(func(that) || that.Value != null)
? that.Error(ML.Get("Validation", "IsRequired"))
: that;
}
对于正常验证,我使用这个:
public Validatable<TProperty> Validate<TProperty>(
Expression<Func<TEntity, TProperty>> expr)
{
return new Validatable<TProperty>(
new ErrorTrackerWrapper(ErrorTracker, expr.Body), expr.Compile()(Value));
}
这一部分称为"RequiredOr"函数:
var header = from name in v.Validate(it => it.Name).Required().MaxLength(Constants.String.NameLength)
from startDate in v.Validate(it => it.StartDate).Required().After(DateTime.Today)
from endDate in v.Validate(it => it.EndDate).Required().After(DateTime.Today)
from endTime in v.Validate(it => it.EndTime).BlockErrors().Required().ReplaceIfInvalid(new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 23, 30, 0))
from requestedCurrency in v.Validate(it => it.RequestedCurrency).Required()
from language1 in v.Validate(it => it.Language1).Required()
from language2 in v.Validate(it => it.Language2)
from language3 in v.Validate(it => it.Language3)
from hasMoreInformation in v.Validate(it => it.HasMoreInformation)
// TODOJP: If "hasMoreInformation" is true, then "moreInformationEmail" has to be required.
from moreInformationEmail in v.Validate(it => it.MoreInformationEmail).IsEmail()//.RequiredOr(p => !hasMoreInformation)
from isAnonymous in v.Validate(it => it.IsAnonymous)
select new AnnouncementHeader(
currentUser,
type,
name,
startDate,
endDate.SetTime(new Time(endTime.Hour, endTime.Minute)),
isAnonymous,
infoField,
requestedCurrency,
language1,
language2,
language3,
hasMoreInformation,
moreInformationEmail);
到目前为止,这是正确的,但在某些方面,它一直告诉我"RequiredOr"部分中的"hasMoreInformation"是NullReferenceException。
我能够将错误追溯到"RequiredOr"函数。
我想检查"HasMoreInformation"是否为真,然后将字段设置为"必需"或否。
我希望你们能理解我想告诉你们的。非常感谢你的帮助。
对于可能为null的对象,在测试字段是否为true之前,必须先测试字段是否存在。违反规则的结果是出现null ref异常。这就是它的工作原理。
如果项可以为null,那么它总是有可能为null。如果默认值,则可以不这样做,但默认值必须具有单一含义,而不是意味着"它可能是默认的"answers"它可以由用户显式设置"。
如果默认值没有意义,那么在验证之前,您假设一个null对象表示有效或无效。
由于我几乎没有上下文,我建议用长格式写出来解决这个问题。然后,您可以使用延迟执行样式(LINQ)进行重新思考。我这么说是因为你似乎只想选择有效的,当项目不为空时,以及其他没有明确说明的东西(基于之后需要检查的注释)。在你把问题弄清楚之前先把它弄清楚。
新:在LINQ建立解决方案之前,仍然坚持最后一行关于解决的内容(我将在这里包括所有形式的延迟执行,而不仅仅是LINQ)。
如果我没有在语句上花费大量时间,您就有了一些LINQ和一些扩展方法(带有链式方法的流畅语法,等等)。所有这些都是延迟执行。如果您下拉符号并在堆栈中弹出,您可能会发现延迟执行的顺序是问题的一部分。这通常是调试大量抽象的唯一方法。(是的,我看到了一个47行嵌套的LINQ语句,其中包含函数指针和扩展方法)
当你使用流体编程风格时,你本质上是在运行一个伪IoC类型的模式,因为最右边的方法会经过下一个方法,直到你一直走到左边。非常糟糕的类似类比的解释,所以我可能会被更正,但你正在使用函数指针来保持流的正确方法。示例:
上校。桑德斯。爱。鸡肉("油炸");
函数指针、扩展方法和RX,天哪!从哲学的角度来看,这是非常巧妙的东西,但如果你不真正理解它是如何运作的,那么很容易出现糟糕的juju。它通常提供非常清晰的语法,但却造成了调试噩梦。
如果你进一步坚持LINQ的说法来选择用餐计划或快餐店,你最终会遇到很多来自不同方向的延迟粘性物质。而且,如果一个位的顺序不正确,则某些代码会在必要的前驱之前运行。由于LINQ和扩展方法使用不同的方法,混合使用它们会增加比特按错误顺序运行的机会。使用符号进行调试通常是破解的唯一方法,因为整个延迟抽象在运行时都会被"编译"。
因此,要结束这篇长文,您需要a)调试并弄清楚为什么会得到null ref(很可能是延迟执行堆栈中的调用顺序错误),或者b)首先使用非延迟方法解决问题(或者一次运行一点延迟的goo?)。