Optionals和Nullable类型有什么区别


15

斯威夫特有Optionals。C#具有Nullable类型。

据我所知,它们具有相同的用途,除了某种类型的值外,它们还存储变量是否有值或未定义(未初始化)的信息。

问题是Optionals仅仅是Nullable名称不同的类型,还是其他概念上的区别?

换句话说,在谈论概念本身时,或者在没有Optionals或的语言的上下文中,Nullables使用术语是否重要?

当用语言实现该功能时,我是否键入类型Optionals<T>或名称都很重要Nullable<T>


从不可知论的角度来看,它们是相同的。也就是说,语言可以区分概念(例如,是否强制执行模式匹配)。
Thomas Eding

C#也可以有选项(这只是一个单子模式):github.com/louthy/language-ext
Den,

2
使用空引用(或空指针,在带指针的语言中为NULL指针)是一种hack,某些语言用来表示可选值,即,一个容器可能只有一个值或根本没有值。这样做的局限性在于,您只能考虑基于引用(或指针)的可选类型。因此,例如,在Java中,如果不将整数包装在对象(例如Integer)中,就不能使整数成为可选的。其他语言提供了可选类型作为可以包装任何其他类型的泛型类型,例如,Haskell中的Maybe,Scala中的Option等。
Giorgio

Answers:


5

即使它们的工作原理非常相似,也有不同的含义。 除Microsoft(此处插入眼球)以外的所有用户都在nullnullable仅在引用上下文中使用。 OptionsMaybes通常被理解为是指两个引用和值,特别是在函数式编程语言,其中引用透明手段没有一个值和一个参考值之间太大的差别。

换句话说,谈论概念本身,或者在没有Optionals或的语言环境中,Nullables使用哪个术语有关系吗?

Options是在广大受众中引起最少混乱的术语。只有C#程序员会认为a Nullable可能适用于值类型,而我认为大多数人至少知道a是什么Option


我认为您的意思是,除了Microsoft和SQL设计人员之外的所有人。
2015年

9

在.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;

C#是一种不纯的功能语言(与F#一样)。同样,F#具有空值。

C#6具有空值胁迫,所以至少有一些你的代码是不是最新的:github.com/dotnet/roslyn/wiki/... roslyn.codeplex.com/discussions/540883
田园

同样的选项很容易实现:github.com/louthy/language-ext
书斋

1
@Den:C#倾向于OOP,而F#倾向于FP。默认情况下,缺少计数和可变性意味着C#不适合进行严格的功能编程。我在答案的结尾提到了零传播。选项确实很容易在C#中实现,但这偏离了问题。
AlexFoxGill 2015年

4
@Den我认为您的评论中的单词选择不多。不纯的功能语言是允许副作用的功能语言。C#可能具有某些功能,您可以使用它们来发挥很大的作用,但这不是功能语言。我想您是说这两种语言都不是100%可以使用的功能,但是F#与OCaml非常接近,后者在大多数情况下都是一种功能性语言。它与功能范例的任何偏差都几乎存在,因此它可以与外部.NET代码进行互操作。典型的例子,null是不是F#类型的有效值。
2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.