斯威夫特有Optionals
。C#具有Nullable
类型。
据我所知,它们具有相同的用途,除了某种类型的值外,它们还存储变量是否有值或未定义(未初始化)的信息。
问题是Optionals
仅仅是Nullable
名称不同的类型,还是其他概念上的区别?
换句话说,在谈论概念本身时,或者在没有Optionals
或的语言的上下文中,Nullables
使用术语是否重要?
当用语言实现该功能时,我是否键入类型Optionals<T>
或名称都很重要Nullable<T>
斯威夫特有Optionals
。C#具有Nullable
类型。
据我所知,它们具有相同的用途,除了某种类型的值外,它们还存储变量是否有值或未定义(未初始化)的信息。
问题是Optionals
仅仅是Nullable
名称不同的类型,还是其他概念上的区别?
换句话说,在谈论概念本身时,或者在没有Optionals
或的语言的上下文中,Nullables
使用术语是否重要?
当用语言实现该功能时,我是否键入类型Optionals<T>
或名称都很重要Nullable<T>
Answers:
即使它们的工作原理非常相似,也有不同的含义。 除Microsoft(此处插入眼球)以外的所有用户都在null
且nullable
仅在引用上下文中使用。 Options
和Maybes
通常被理解为是指两个引用和值,特别是在函数式编程语言,其中引用透明手段没有一个值和一个参考值之间太大的差别。
换句话说,谈论概念本身,或者在没有
Optionals
或的语言环境中,Nullables
使用哪个术语有关系吗?
Options
是在广大受众中引起最少混乱的术语。只有C#程序员会认为a Nullable
可能适用于值类型,而我认为大多数人至少知道a是什么Option
。
在.NET中,有两类类型:引用和值(int,double,结构,枚举等)。它们之间的差异是引用可以是null
,而值不能是。因此,如果您具有值类型,并且想要传达“可选”或“未知”语义,则可以使用进行修饰Nullable<>
。请注意,Nullable<>
受类型限制,该类型仅接受值类型(它有一个where T : struct
子句)。Nullable<>
编译器还提供了特殊的功能,从而null
可以保护值免受NullReferenceExceptions
:
string x = null;
x.ToString(); // throws a NullReferenceException
int? y = null;
y.ToString(); // returns ""
在功能语言(例如Scala,F#,Haskell,Swift等)中null
,不存在是很常见的。这是因为总的来说,人们认为存在null
是一个坏主意,而语言设计师已决定通过不允许它来解决此问题。
这意味着我们再次需要某种方式来表示这些语言中的非值。输入Option
类型(名称有所不同,Maybe
在Haskell中称为)。这样做的相似之处Nullable
在于,它包装类型以添加值是“ None”或“ Unknown”等的情况。
真正的区别在于实现的语言为您提供的额外功能Option
。举个例子,Option.map
(用伪代码):
function Option<T2> Option.map(opt: Option<T1>, mapFunc: T1 -> T2) {
if (opt is None) return None
else return Option<T2>(mapFunc(opt.Value))
}
像这样的链接函数Option.map
是避免在C#中到处可见的典型null检查样板的有效方法:
if (service == null)
return null;
var x = service.GetValue();
if (x == null || x.Property == null)
return null;
return x.Property.Value;
C#中的Nullable等效项为:
public static Nullable<T2> Map<T1, T2>(this Nullable<T1> nullable, Func<T1, T2> f)
where T1 : struct
where T2 : struct
{
if (!nullable.HasValue) return (T2?)null;
else return (T2?) f(nullable.Value);
}
但是,由于它仅适用于值类型,因此在C#中的实用程序有限。
新版本的C#提供了“空传播”运算符(?.
),该运算符类似于该Option.map
函数,但仅适用于方法和属性访问器。以上示例将被重写
return service?.GetValue()?.Property?.Value;
null
是不是F#类型的有效值。