ข้อแตกต่างระหว่าง Optionals และประเภท Nullable คืออะไร


15

Optionalsสวิฟท์มี C # มีNullableประเภท

เท่าที่ฉันสามารถบอกได้ทั้งวัตถุประสงค์เดียวกันนอกจากค่าของบางประเภทพวกเขาเก็บข้อมูลว่าตัวแปรมีค่าหรือไม่ได้กำหนด (ไม่เตรียม)

คำถามเป็นOptionalsเพียงNullableประเภทที่มีชื่อแตกต่างกันหรือมีความแตกต่างทางแนวคิดอื่น ๆ

กล่าวอีกนัยหนึ่งคือการพูดคุยเกี่ยวกับแนวคิดของตนเองหรือในบริบทของภาษาที่ไม่มีOptionalsหรือNullablesมันมีความสำคัญต่อการใช้คำศัพท์หรือไม่?

เมื่อใช้งานฟังก์ชั่นนั้นในภาษามันไม่สำคัญว่าฉันจะพิมพ์ชื่อOptionals<T>หรือNullable<T>


จากมุมมองที่ไม่เชื่อเรื่องภาษาพวกเขาเหมือนกัน ที่กล่าวว่าภาษาอาจแตกต่างแนวคิด (เช่นบังคับใช้การจับคู่รูปแบบหรือไม่)
Thomas Eding

C # สามารถมีตัวเลือกได้เช่นกัน (เป็นเพียงรูปแบบ monadic): github.com/louthy/language-ext
Den

2
การใช้การอ้างอิงแบบ null (หรือตัวชี้ NULL ในภาษาที่มีตัวชี้) เป็นแฮ็คที่บางภาษาใช้เพื่อแทนค่าทางเลือกเช่นคอนเทนเนอร์ที่อาจมีหนึ่งค่าหรือไม่มีค่าเลย นี่เป็นข้อ จำกัด ที่คุณสามารถพิจารณาได้เฉพาะประเภทที่เป็นทางเลือกซึ่งอ้างอิงจากการอ้างอิง (หรือตัวชี้) ดังนั้นเช่นใน Java คุณไม่สามารถทำการเลือกจำนวนเต็มโดยไม่ต้องหุ้มมันในวัตถุ (เช่น Integer) ภาษาอื่น ๆ ให้ประเภทที่เป็นตัวเลือกเป็นประเภททั่วไปที่สามารถห่อประเภทอื่น ๆ ได้เช่นบางทีใน Haskell ตัวเลือกใน Scala และอื่น ๆ
Giorgio

คำตอบ:


5

มีความหมายแฝงที่แตกต่างกันแม้ว่าพวกเขาจะทำงานคล้ายกันมาก ทุกคนยกเว้น Microsoft (ใช้ eye-roll ที่นี่) ใช้nullและnullableเฉพาะในบริบทของการอ้างอิง OptionsและMaybesเป็นที่เข้าใจกันโดยทั่วไปในการอ้างถึงทั้งการอ้างอิงและค่านิยมโดยเฉพาะอย่างยิ่งในภาษาโปรแกรมการทำงานที่ความโปร่งใสในการอ้างอิงหมายถึงไม่มีความแตกต่างระหว่างค่าและการอ้างอิง

กล่าวอีกนัยหนึ่งคือการพูดคุยเกี่ยวกับแนวคิดเองหรือในบริบทของภาษาที่ไม่มีOptionalsหรือNullablesมันมีความสำคัญหรือไม่ที่ใช้กับคำศัพท์

Optionsเป็นคำที่ทำให้เกิดความสับสนน้อยที่สุดในหมู่ผู้ชมในวงกว้าง มีเพียงโปรแกรมเมอร์ C # เท่านั้นที่คิดว่าNullableอาจนำไปใช้กับประเภทของค่าได้และฉันคิดว่าอย่างน้อยพวกเขาส่วนใหญ่ตระหนักถึงสิ่งที่Optionเป็น


ทุกคนยกเว้น Microsoft และผู้ออกแบบ SQL ฉันคิดว่าคุณหมายถึง
จูลส์

9

ใน. NET มีประเภทอยู่สองประเภท: การอ้างอิงและค่า (int, double, structs, enums ฯลฯ ) ท่ามกลางความแตกต่างของพวกเขาคือความจริงที่ว่าการอ้างอิงสามารถnullในขณะที่ค่าไม่สามารถ ดังนั้นหากคุณมีประเภทค่าและต้องการนำเสนอ "ตัวเลือก" หรือ "ไม่ทราบ" Nullable<>ความหมายคุณสามารถประดับด้วย โปรดทราบว่าNullable<>ถูก จำกัด โดยประเภทที่จะยอมรับเฉพาะประเภทค่า (มันมีwhere T : structข้อ) Nullable<>ยังมีค่าใช้จ่ายพิเศษจากคอมไพเลอร์โดยที่nullค่าถูกป้องกันจากNullReferenceExceptions:

string x = null;
x.ToString(); // throws a NullReferenceException

int? y = null;
y.ToString(); // returns ""

ในภาษาการทำงาน (เช่นสกาล่า, F # Haskell, สวิฟท์ ฯลฯ ) มันเป็นเรื่องธรรมดาสำหรับnullการได้อยู่ นี้เป็นเพราะในคนทั้งมองว่าการดำรงอยู่ของnullเป็นความคิดที่ดีและนักออกแบบภาษาได้ตัดสินใจที่จะแก้ไขปัญหานี้โดยไม่อนุญาตให้มัน

ซึ่งหมายความว่าเราต้องการวิธีที่จะแสดงค่าที่ไม่ใช่ค่าในภาษาเหล่านี้อีกครั้ง ป้อนOptionประเภท (ระบบการตั้งชื่อแตกต่างกันไปซึ่งเรียกว่าMaybeใน Haskell) นี่เป็นงานที่คล้ายกับNullableที่มันล้อมรอบประเภทเพื่อเพิ่มเคสที่ค่าเป็น "None" หรือ "Unknown" เป็นต้น

Optionความแตกต่างที่แท้จริงอยู่ในฟังก์ชั่นพิเศษให้กับคุณโดยภาษาที่ใช้ เป็นตัวอย่างใช้Option.map(ใน pseudocode):

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 #:

if (service == null)
    return null;
var x = service.GetValue();
if (x == null || x.Property == null)
    return null;
return x.Property.Value;

ค่า Nullable ที่เทียบเท่าใน C # จะเป็น:

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 # นำเสนอตัวดำเนินการ "การขยายพันธุ์แบบ null" ( ?.) ซึ่งคล้ายกับOption.mapฟังก์ชันยกเว้นมันจะใช้ได้กับวิธีการและตัวเข้าถึงคุณสมบัติเท่านั้น ตัวอย่างข้างต้นจะถูกเขียนใหม่

return service?.GetValue()?.Property?.Value;

C # เป็นภาษาที่ใช้งานไม่ได้ (เช่นเดียวกับ F #) F # ก็มีค่า Null ด้วยเช่นกัน
Den

C # 6 มีค่าบังคับเป็นโมฆะดังนั้นอย่างน้อยโค้ดบางอย่างของคุณก็ยังไม่ทันสมัย: github.com/dotnet/roslyn/wiki/… roslyn.codeplex.com/discussions/540883
Den

นอกจากนี้ตัวเลือกยังใช้งานง่าย: github.com/louthy/language-ext
Den

1
@Den: C # โน้มตัวไปทาง OOP ในขณะที่ F # โน้มตัวไปยัง FP การขาดการแก้ปัญหาและความไม่แน่นอนโดยค่าเริ่มต้นหมายถึง C # ไม่เหมาะสำหรับการเขียนโปรแกรมการทำงานที่จริงจัง ฉันพูดถึงการขยายพันธุ์โมฆะในตอนท้ายของคำตอบ ตัวเลือกนั้นง่ายต่อการนำไปใช้ใน C # แต่แฝงไปด้วยคำถาม
AlexFoxGill

4
@Den ฉันคิดว่ามีบางคำที่ไม่ดีในความคิดเห็นของคุณ ภาษาหน้าที่ไม่บริสุทธิ์เป็นภาษาที่ใช้งานได้ซึ่งอนุญาตให้มีผลข้างเคียง C # อาจมีคุณสมบัติการใช้งานบางอย่างและคุณสามารถใช้เพื่อให้ได้ผลดี แต่ไม่ใช่ภาษาที่ใช้งานได้ ฉันเดาว่าคุณหมายถึงว่าไม่มีภาษาใดที่สามารถใช้งานได้ 100% แต่ F # นั้นใกล้เคียงกับ OCaml ซึ่งส่วนใหญ่แล้วเป็นภาษาที่ใช้งานได้จริง สิ่งที่เบี่ยงเบนจากกระบวนทัศน์การทำงานส่วนใหญ่มีอยู่เพื่อให้สามารถทำงานร่วมกับรหัส. NET ต่างประเทศ ตรงประเด็นnullไม่ใช่ค่าที่ถูกต้องสำหรับประเภท F #
Doval
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.