C# 调用IEnumerable时是否应该检查默认值<;T>;。FirstOrDefault,其中T:struct
我有一个C# 调用IEnumerable时是否应该检查默认值<;T>;。FirstOrDefault,其中T:struct,c#,C#,我有一个structs序列,如下所示: struct Foo { } ... // somewhere else var foos = GetListOfFoos(); ... // somewhere else var foo = foos.FirstOrDefault(); 现在,我是否应该继续使用刚才检索到的foo,而不必担心可空性,当然,因为structs是值类型,所以不可空 只是觉得有点担心 我知道这是一个愚蠢的问题,答案是,“是的,只使用它而不检查null。”但我不知道我为
struct
s序列,如下所示:
struct Foo { }
...
// somewhere else
var foos = GetListOfFoos();
...
// somewhere else
var foo = foos.FirstOrDefault();
现在,我是否应该继续使用刚才检索到的foo
,而不必担心可空性,当然,因为structs
是值类型,所以不可空
只是觉得有点担心
我知道这是一个愚蠢的问题,答案是,“是的,只使用它而不检查null。”但我不知道我为什么问这个问题,甚至不知道这里的问题是什么
我没有在这里检查可空性,所以没有遗漏任何东西,对吗?放入IEnumerable
中的结构不能有无效状态,对吗
当然,我知道如果
Foo
的成员未初始化,因为它声明了一个未初始化每个成员的参数化ctor,那么Foo
实例的一个或多个成员将处于不可使用状态。但是同样地,该列表中的Foo
的每个实例都相当于一些东西,并且没有必要检查null或任何东西,因为没有default(Foo)
这样的东西,对吗?当然,只是确认一下。即使值类型不为null,您也应该担心该值是否为默认值,如果这是异常值或非预期值
没有默认值(Foo)
当然,它将返回此类型的实例,其中所有成员都初始化为其默认值
如果采用f.e.struct Guid
,则default(Guid)
返回一个等于Guid.Empty
或new Guid()
的实例
因此,我的建议是,不要与default(yourStruct)
进行比较,因为如果默认结构可能是有效实例,那么这可能会导致严重的错误。相反,您可以使用Any
:
bool containsAny = foos.Any();
if(containsAny)
{
Foo firstFoo = foos.First();
}
- 返回引用类型(类类型和接口类型)的
null
- 数值类型为零
- 对于用户定义的结构,它返回初始化为零位模式的结构,根据每个成员是值类型还是引用类型,该模式为每个成员生成0或null。对于可为null的值类型,默认值返回一个
,它与任何结构一样初始化System.nullable
struct Guid
,则default(Guid)
返回一个等于Guid.Empty
或new Guid()
的实例
因此,我的建议是,不要与default(yourStruct)
进行比较,因为如果默认结构可能是有效实例,那么这可能会导致严重的错误。相反,您可以使用Any
:
bool containsAny = foos.Any();
if(containsAny)
{
Foo firstFoo = foos.First();
}
- 返回引用类型(类类型和接口类型)的
null
- 数值类型为零
- 对于用户定义的结构,它返回初始化为零位模式的结构,根据每个成员是值类型还是引用类型,该模式为每个成员生成0或null。对于可为null的值类型,默认值返回一个
,它与任何结构一样初始化System.nullable
T
是struct
,则无法检查null
:它永远不会是null
,列表/序列中的实际“零”(等效值)将与“否列表/序列中没有任何值”无法区分
不,您不需要在此处检查
null
。如果t
是struct
,则无法检查null
:它永远不会是null
,列表/序列中的真正“零”(等效值)将与“不,列表/序列中没有任何值”无法区分
不,您不需要在这里检查
null
。如果没有看到GetListofOOS
的声明,我不愿意给您一个保证,但是如果它确实返回了列表,那么您是对的,GetFirstOrDefault
将抛出异常或返回一个结构值,而不是null(在这种情况下);没有不稳定(即垃圾)状态或值它们是默认值(Foo)
,如果foos
为空,这就是Foo
的状态。你的问题似乎是关于结构是如何默认初始化的。@Lee这很奇怪,因为我在检查if(foo==default(foo))
时遇到了一个编译器错误。编译器说,“运算符==不能应用于Foo和Foo类型的操作数。”是的,这是因为您没有为Foo
实现Operator=
。您应该能够执行Foo f=default(Foo);foo.SomeMethod()
。如果没有看到getListofoos的声明,我不愿意给您一个保证,但是如果它确实返回了List
,那么您是正确的,.GetFirstOrDefault
将抛出异常或返回结构值,永远不会为null(在本例中)。如果getListofoos()
不返回任何项,FirstOrDefault()
将创建一个Foo
的实例,所有字段都分配为零(0
对于int
,double
的0.0
,false
对于bool
,null
对于任何参考值等);无不稳定(即垃圾)状态或值