C# 如何优雅地保护方法不受未初始化接口参数的影响

C# 如何优雅地保护方法不受未初始化接口参数的影响,c#,C#,给定接口类型的方法参数,如果使用者可以提供引用类型或未知值类型,即开发人员在实现时不知道的结构类型,我如何保护方法不受未初始化参数的影响?我不想检查传入属性的特定属性值。我已经在这个主题上做了很多搜索,但还没有找到我想要的确切信息 例如 。。。在别的班 public void DoSomething(IFoo foo) { // Check if foo is null or default of some value type // Just like foo == nul

给定接口类型的方法参数,如果使用者可以提供引用类型或未知值类型,即开发人员在实现时不知道的结构类型,我如何保护方法不受未初始化参数的影响?我不想检查传入属性的特定属性值。我已经在这个主题上做了很多搜索,但还没有找到我想要的确切信息

例如

。。。在别的班

public void DoSomething(IFoo foo)
{
     // Check if foo is null or default of some value type
     // Just like foo == null, this doesn't work for a value type 
     if (foo == default(IFoo)) throw new ArgumentNullException(nameof(foo));

}

当传递给接受此结构实现的接口的方法时,FooStruct将被装箱,因此您可以将其与null进行比较。您可能想阅读有关装箱的内容,本文可能也会有所帮助:

FooStruct在传递给接受此结构实现的接口的方法时将被装箱,因此您可以将其与null进行比较。您可能想阅读有关装箱的内容,也许本文也会有所帮助:

如果方法不会因为初始化值而实际中断,则不要担心初始化值。与
null
相比就足够了,因为您真正要做的是尝试使用指定的参数名称抛出一个早期异常,而不是可怕且不具体的
NullReferenceException
throw
的全部目的是添加更具体的细节,以便调用实现能够很容易地修复它们所做的错误(或者至少报告一个更知情的、因而更有意义的bug)。一个很好的例子是,由于
计数
;,Linq方法不需要费心抛出


这就是说,如果
FooStruct
中存在无效的内容,那么它应该为该无效性抛出一个特定的异常,而不是某种误导性的
ArgumentNullException
。例如,考虑<代码>默认(int) <代码> 0 ,<代码> 0 完全有效地传递到某些方法中,而如果不是,我们期望<代码> ArgumentOutOfRange < /C> >(希望具有有效范围),而不是代码> > AgMUMUTNOT/<代码>,我们知道的值是(并且永远不会)。
null

如果方法不会因为初始化值而实际中断,则不要担心初始化值。与
null
相比就足够了,因为您真正要做的是尝试使用指定的参数名称抛出一个早期异常,而不是可怕且不具体的
NullReferenceException
throw
的全部目的是添加更具体的细节,以便调用实现能够很容易地修复它们所做的错误(或者至少报告一个更知情的、因而更有意义的bug)。一个很好的例子是,由于
计数
;,Linq方法不需要费心抛出


这就是说,如果
FooStruct
中存在无效的内容,那么它应该为该无效性抛出一个特定的异常,而不是某种误导性的
ArgumentNullException
。例如,考虑<代码>默认(int) <代码> 0 ,<代码> 0 完全有效地传递到某些方法中,而如果不是,我们期望<代码> ArgumentOutOfRange < /C> >(希望具有有效范围),而不是代码> > AgMUMUTNOT/<代码>,我们知道的值是(并且永远不会)。
null

对于不可
null
struct
,您可以将您的结构与
新的MyStruct()
(下面的Activation.CreateInstance)进行比较

上述代码输出以下内容:

True
False
True
False

对于不可
为空的
结构
,您可以将您的结构与
新的MyStruct()
(下面的Activation.CreateInstance)进行比较

上述代码输出以下内容:

True
False
True
False

从以下方面对代码进行推理通常是有帮助的

每个方法都有一些先决条件——被调用方应该满足的条件,以及后置条件——方法保证对有效输入执行的条件

例如,在方法
中,y除以x
x
显然应该是非零ant,这是一个合理的先决条件。这种情况的后置条件是结果小于或等于提供的
y

您只能在有效的输入上保证有效的行为,因此,仅仅因为默认结构值是默认的,就没有意义使用默认结构值——而是使用一些特定和合理的断言


ArgumentNullException
之所以广泛传播,仅仅是因为参数通常是以某种方式使用的,因此验证它们是否为null是有意义的,否则您的方法将失败。

根据参数对代码进行推理通常是有帮助的

每个方法都有一些先决条件——被调用方应该满足的条件,以及后置条件——方法保证对有效输入执行的条件

例如,在方法
中,y除以x
x
显然应该是非零ant,这是一个合理的先决条件。这种情况的后置条件是结果小于或等于提供的
y

您只能在有效的输入上保证有效的行为,因此,仅仅因为默认结构值是默认的,就没有意义使用默认结构值——而是使用一些特定和合理的断言


ArgumentNullException
之所以广泛传播,仅仅是因为参数通常以某种方式使用,因此验证它们是否为null是有意义的,否则您的方法将失败。

我不明白问题是什么。您说您不想检查特定属性,并且您已经在检查参数是否为null,所以。。。。问题是什么?我认为如果您通过了
default(FooStruct)
,那么您应该假设这就是所通过的。空对象很容易被检测为未初始化的对象,但未初始化的结构和其值相同的结构之间没有区别
True
False
True
False