ต้องการอะไร: Nullable <T> .HasValue หรือ Nullable <T>! = null?


437

ฉันมักจะใช้Nullable<>.HasValueเพราะฉันชอบความหมาย อย่างไรก็ตามเมื่อเร็ว ๆ นี้ฉันกำลังทำงานกับ codebase ที่มีอยู่ของคนอื่นซึ่งพวกเขาใช้เป็นNullable<> != nullพิเศษแทน

มีเหตุผลที่จะใช้อย่างใดอย่างหนึ่งมากกว่าอื่น ๆ หรือมันคือการตั้งค่าอย่างหมดจด?

  1. int? a;
    if (a.HasValue)
        // ...
    

เมื่อเทียบกับ

  1. int? b;
    if (b != null)
        // ...
    

9
ฉันถามคำถามที่คล้ายกัน ... ได้คำตอบที่ดี: stackoverflow.com/questions/633286/…
nailitdown

3
โดยส่วนตัวแล้วฉันจะใช้HasValueเพราะฉันคิดว่าคำต่างๆมักอ่านง่ายกว่าสัญลักษณ์ ทุกอย่างขึ้นอยู่กับคุณและสิ่งที่เหมาะกับสไตล์ที่คุณมีอยู่
Jake Petroules

1
.HasValueทำให้รู้สึกมากกว่าที่มันจะระบุประเภทเป็นประเภทT?มากกว่าประเภทที่สามารถ nullable เช่นสตริง
3791372

คำตอบ:


476

คอมไพเลอร์แทนที่การเปรียบเทียบค่า null ด้วยการเรียกHasValueดังนั้นจึงไม่มีความแตกต่างที่แท้จริง เพียงแค่ทำสิ่งใดก็ตามที่สามารถอ่านได้มากขึ้น / ทำให้คุณและเพื่อนร่วมงานของคุณเข้าใจได้ง่ายขึ้น


86
ฉันจะเพิ่มเข้าไปใน "สิ่งใดที่สอดคล้องกันมากขึ้น / ตามสไตล์การเข้ารหัสที่มีอยู่"
Josh Lee

20
ว้าว. ฉันเกลียดน้ำตาลประโยคนี้ int? x = nullให้ภาพลวงตาว่าอินสแตนซ์ที่สามารถลบล้างได้เป็นประเภทอ้างอิง แต่ความจริงก็คือ Nullable <T> เป็นประเภทค่า รู้สึกว่าฉันได้รับ NullReferenceException ทำ: int? x = null; Use(x.HasValue).
KFL

11
@KFL ถ้ารบกวนน้ำตาลประโยคคุณเพียงแค่ใช้แทนNullable<int> int?
โคลจอห์นสัน

24
ในช่วงแรกของการสร้างแอปพลิเคชั่นคุณอาจคิดว่ามันเพียงพอที่จะใช้ประเภทของค่าที่เป็นโมฆะในการจัดเก็บข้อมูลบางอย่างเท่านั้นที่จะรับรู้หลังจากที่คุณต้องการคลาสที่เหมาะสมสำหรับวัตถุประสงค์ของคุณ การเขียนรหัสต้นฉบับเพื่อเปรียบเทียบกับค่า Null นั้นมีข้อดีที่คุณไม่จำเป็นต้องค้นหา / แทนที่การเรียกใช้ HasValue () ทุกครั้งด้วยการเปรียบเทียบค่า Null
Anders

15
มันสวยโง่ที่จะบ่นเกี่ยวกับความสามารถในการตั้งค่า Nullable เพื่อโมฆะหรือเปรียบเทียบกับ null ระบุว่าของที่เรียกว่า Nullable ปัญหาคือคนกำลังทำให้ "ประเภทการอ้างอิง" กับ "อาจเป็นโมฆะ" แต่นั่นเป็นความสับสนทางความคิด ในอนาคต C # จะมีประเภทอ้างอิงที่ไม่เป็นโมฆะ
Jim Balter

48

ฉันชอบ(a != null)เพื่อให้ไวยากรณ์ตรงกับประเภทอ้างอิง


11
ซึ่งเป็นความเข้าใจผิดค่อนข้างแน่นอนเนื่องจากNullable<>เป็นไม่ได้ชนิดอ้างอิง
Luaan

9
ใช่ แต่ความจริงมักจะไม่ค่อยสำคัญเท่าที่ควร
cbp

31
มันทำให้เข้าใจผิดสับสนเท่านั้น การใช้ไวยากรณ์ที่สอดคล้องกันสำหรับสองประเภทที่แตกต่างกันไม่ได้หมายความว่าพวกเขาเป็นประเภทเดียวกัน C # มีประเภทการอ้างอิงที่เป็นโมฆะ (ประเภทการอ้างอิงทั้งหมดเป็นโมฆะในขณะนี้ แต่จะเปลี่ยนในอนาคต) และประเภทค่าที่ไม่สามารถใช้ได้ การใช้ไวยากรณ์ที่สอดคล้องกันสำหรับประเภท nullable ทั้งหมดทำให้รู้สึก ไม่ได้หมายความว่าประเภทค่า nullable เป็นประเภทอ้างอิงหรือประเภทอ้างอิง nullable เป็นประเภทค่า
Jim Balter

ฉันชอบHasValueเพราะอ่านได้มากกว่า!= null
คอนราด

ความสอดคล้องของการเข้ารหัสสามารถอ่านได้มากขึ้นถ้าคุณไม่ผสมผสานสไตล์การเขียนรหัสเดียวกัน เนื่องจากสถานที่บางแห่งไม่มีคุณสมบัติ .HasValue ดังนั้นจึงใช้ตั้งแต่! = null เพื่อความสอดคล้องที่เพิ่มขึ้น ในความมั่นใจของฉัน
ColacX

21

ฉันได้ทำการวิจัยเกี่ยวกับเรื่องนี้โดยใช้วิธีการที่แตกต่างกันเพื่อกำหนดค่าให้กับ int ไม่สามารถ นี่คือสิ่งที่เกิดขึ้นเมื่อฉันทำสิ่งต่าง ๆ ควรชี้แจงสิ่งที่เกิดขึ้น โปรดทราบ: Nullable<something>หรือชวเลขsomething?เป็นโครงสร้างที่คอมไพเลอร์ดูเหมือนว่าจะทำงานมากมายเพื่อให้เราใช้เป็นโมฆะราวกับว่าเป็นคลาส
ดังที่คุณเห็นด้านล่างSomeNullable == nullและSomeNullable.HasValueจะส่งกลับค่าที่คาดหวังจริงหรือเท็จเสมอ แม้ว่าจะไม่ได้แสดงไว้ด้านล่าง แต่SomeNullable == 3ก็ใช้ได้เช่นกัน (สมมติว่า SomeNullable คือ an int?)
ในขณะที่SomeNullable.Valueเราได้รับข้อผิดพลาด runtime ถ้าเราได้รับมอบหมายไปnull SomeNullableในความเป็นจริงในกรณีเดียวที่ nullables อาจทำให้เรามีปัญหาด้วยการรวมกันของผู้ประกอบการมากเกินไป, มากไปobject.Equals(obj) วิธีการและการเพิ่มประสิทธิภาพของคอมไพเลอร์และธุรกิจลิง

นี่คือคำอธิบายของโค้ดที่ฉันรันและผลลัพธ์ที่ผลิตในเลเบล:

int? val = null;
lbl_Val.Text = val.ToString(); //Produced an empty string.
lbl_ValVal.Text = val.Value.ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValEqNull.Text = (val == null).ToString(); //Produced "True" (without the quotes)
lbl_ValNEqNull.Text = (val != null).ToString(); //Produced "False"
lbl_ValHasVal.Text = val.HasValue.ToString(); //Produced "False"
lbl_NValHasVal.Text = (!(val.HasValue)).ToString(); //Produced "True"
lbl_ValValEqNull.Text = (val.Value == null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValValNEqNull.Text = (val.Value != null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")

ตกลงให้ลองวิธีการเริ่มต้นต่อไป:

int? val = new int?();
lbl_Val.Text = val.ToString(); //Produced an empty string.
lbl_ValVal.Text = val.Value.ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValEqNull.Text = (val == null).ToString(); //Produced "True" (without the quotes)
lbl_ValNEqNull.Text = (val != null).ToString(); //Produced "False"
lbl_ValHasVal.Text = val.HasValue.ToString(); //Produced "False"
lbl_NValHasVal.Text = (!(val.HasValue)).ToString(); //Produced "True"
lbl_ValValEqNull.Text = (val.Value == null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValValNEqNull.Text = (val.Value != null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")

ทุกอย่างเหมือนเดิม โปรดทราบว่าการกำหนดค่าเริ่มต้นด้วยint? val = new int?(null);ด้วย null ที่ส่งผ่านไปยังตัวสร้างจะทำให้เกิดข้อผิดพลาดในการคอมไพล์เนื่องจากค่า VALUE ของวัตถุที่เป็นโมฆะนั้นไม่เป็นโมฆะ มันเป็นเพียงวัตถุห่อหุ้มตัวเองที่สามารถเป็นโมฆะ

ในทำนองเดียวกันเราจะได้รับข้อผิดพลาดในการรวบรวมเวลาจาก:

int? val = new int?();
val.Value = null;

ไม่ต้องพูดถึงว่าval.Valueเป็นคุณสมบัติแบบอ่านอย่างเดียวหมายความว่าเราไม่สามารถใช้สิ่งที่ชอบได้:

val.Value = 3;

แต่อีกครั้งตัวดำเนินการแปลงโดยนัยที่มีมากเกินไปทำให้เรา:

val = 3;

ไม่จำเป็นต้องกังวลเกี่ยวกับ polysomthing whatchamacallits ตราบใดที่มันใช้งานได้ :)


5
"โปรดทราบว่า: <บางสิ่งที่ทำให้เป็นโมฆะ> หรือบางสิ่งที่จดชวเลข? เป็นคลาส" นี่มันผิด! Nullable <T> เป็นโครงสร้าง มันเกินเท่ากับและผู้ประกอบการ == เพื่อกลับจริงเมื่อเทียบกับ null คอมไพเลอร์ไม่ได้ผลสำหรับการเปรียบเทียบนี้
andrewjs

1
@andrewjs - คุณถูกต้องว่ามันเป็น struct (ไม่ใช่คลาส) แต่คุณผิดที่มันเกินพิกัด == โอเปอเรเตอร์ หากคุณพิมพ์Nullable<X>ใน VisualStudio 2013 และ F12 คุณจะเห็นว่ามันเกินพิกัดการแปลงไปและกลับจากXและEquals(object other)วิธีการ อย่างไรก็ตามฉันคิดว่าตัวดำเนินการ == ใช้วิธีการนั้นตามค่าเริ่มต้นดังนั้นผลจะเหมือนกัน จริง ๆ แล้วฉันตั้งใจจะปรับปรุงคำตอบนี้ในขณะนี้ แต่ฉันขี้เกียจและ / หรือไม่ว่าง ความคิดเห็นนี้จะต้องทำตอนนี้ :)
เพอร์ริน Larson

ฉันทำการตรวจสอบอย่างรวดเร็วผ่าน ildasm และคุณพูดถูกเกี่ยวกับคอมไพเลอร์ที่ทำเวทย์มนตร์ การเปรียบเทียบวัตถุ Nullable <T> ให้เป็นโมฆะจริง ๆ แล้วแปลเป็นการเรียกไปยัง HasValue ! ที่น่าสนใจ
andrewjs

3
@andrewjs ที่จริงแล้วคอมไพเลอร์ทำงานมากมายเพื่อเพิ่มประสิทธิภาพของว่างเปล่า ตัวอย่างเช่นหากคุณกำหนดค่าให้กับประเภทที่สามารถลบล้างได้จริงมันจะไม่สามารถเปลี่ยนเป็นประเภทใด ๆ ได้เลย (เช่น, int? val = 42; val.GetType() == typeof(int)) ดังนั้นไม่เพียง แต่จะเป็นโมฆะที่เป็นโครงสร้างที่สามารถเป็นโมฆะได้ แต่มันก็มักจะไม่เป็นโมฆะเลย! : D วิธีเดียวกันเมื่อคุณใส่ค่าที่ไม่สามารถใช้งานได้คุณกำลังชกมวยintไม่ใช่int?- และเมื่อint?ไม่มีค่าคุณจะได้รับnullแทนที่จะเป็นค่า nullable ที่บรรจุอยู่ มันเป็นพื้นหมายความว่ามีค่าใช้จ่ายใด ๆ ไม่ค่อยจากการใช้อย่างถูกต้อง nullable :)
Luaan

1
@JimBalter จริงเหรอ? นั่นเป็นเรื่องที่น่าสนใจมาก ดังนั้น profiler หน่วยความจำบอกอะไรคุณเกี่ยวกับเขตข้อมูลโมฆะในชั้นเรียน? คุณจะประกาศประเภทค่าที่สืบทอดจากประเภทค่าอื่นใน C # ได้อย่างไร คุณจะประกาศประเภท nullable ของคุณเองที่ทำงานเช่นเดียวกับประเภท nullable NET ได้อย่างไร ตั้งแต่เมื่อใดNullที่ประเภทใน. NET คุณสามารถชี้ไปที่ส่วนในข้อกำหนด CLR / C # ที่กล่าวไว้ได้หรือไม่? Nullables มีการกำหนดไว้เป็นอย่างดีในสเปค CLR พฤติกรรมของพวกเขาไม่มี "การดำเนินการของนามธรรม" - มันเป็นสัญญา แต่ถ้าสิ่งที่ดีที่สุดที่คุณสามารถทำได้คือการโจมตีด้วยโฆษณา
Luaan

13

ใน VB.Net อย่าใช้ "IsNot Nothing" เมื่อคุณสามารถใช้ ".HasValue" ฉันเพิ่งแก้ไข "การดำเนินการสามารถเสถียร runtime" ข้อผิดพลาดความน่าเชื่อถือปานกลางโดยแทนที่ "IsNot Nothing" ด้วย ".HasValue" ในที่เดียว ฉันไม่เข้าใจว่าทำไม แต่มีบางสิ่งเกิดขึ้นแตกต่างกันในคอมไพเลอร์ ฉันจะสมมติว่า "! = null" ใน C # อาจมีปัญหาเดียวกัน


8
ฉันต้องการHasValueเนื่องจากการอ่าน IsNot Nothingเป็นการแสดงออกที่น่าเกลียดจริงๆ (เพราะการปฏิเสธคู่)
Stefan Steinegger

12
@steffan "IsNot Nothing" ไม่ใช่การปฏิเสธสองทาง "ไม่มีอะไร" ไม่ได้เป็นเชิงลบ แต่เป็นปริมาณที่ไม่ต่อเนื่องแม้อยู่นอกขอบเขตของการเขียนโปรแกรม "ปริมาณนี้ไม่ใช่อะไรเลย" คือทางไวยากรณ์เช่นเดียวกับการพูดว่า "ปริมาณนี้ไม่เป็นศูนย์" และไม่เป็นลบสองเท่า
jmbpiano

5
ไม่ใช่ว่าฉันไม่ต้องการที่จะไม่เห็นด้วยกับการขาดความจริงที่นี่ แต่มาในตอนนี้ IsNot ไม่มีอะไรชัดเจนลบดีเกินไป ทำไมไม่เขียนสิ่งที่เป็นบวกและชัดเจนเช่น HasValue นี่ไม่ใช่การทดสอบไวยากรณ์ แต่เป็นการเขียนโปรแกรมซึ่งวัตถุประสงค์หลักคือความชัดเจน
Randy Gamage

3
jmbpiano: ฉันยอมรับว่ามันไม่ใช่การปฏิเสธสองเท่า แต่เป็นการปฏิเสธเพียงครั้งเดียวและนั่นเกือบจะน่าเกลียดและไม่ชัดเจนเท่ากับการแสดงออกในเชิงบวกที่เรียบง่าย
Kaveh Hadjari

0

หากคุณใช้ linq และต้องการทำให้รหัสของคุณสั้นฉันขอแนะนำให้ใช้เสมอ !=null

และนี่คือเหตุผล:

ลองจินตนาการว่าเรามีคลาสที่Fooมีตัวแปรสองตัวที่ไม่มีค่าได้SomeDouble

public class Foo
{
    public double? SomeDouble;
    //some other properties
}   

หากบางแห่งในรหัสของเราเราต้องการให้ Foo ทั้งหมดมีค่าไม่เป็นโมฆะค่า DoubleDouble จากคอลเล็กชันของ Foo (สมมติว่า foos บางอย่างในคอลเลกชันสามารถเป็นโมฆะได้) เราจะจบด้วยวิธีการเขียนฟังก์ชันของเราอย่างน้อยสามวิธี ใช้ C # 6):

public IEnumerable<Foo> GetNonNullFoosWithSomeDoubleValues(IEnumerable<Foo> foos)
{
     return foos.Where(foo => foo?.SomeDouble != null);
     return foos.Where(foo=>foo?.SomeDouble.HasValue); // compile time error
     return foos.Where(foo=>foo?.SomeDouble.HasValue == true); 
     return foos.Where(foo=>foo != null && foo.SomeDouble.HasValue); //if we don't use C#6
}

และในสถานการณ์เช่นนี้ฉันแนะนำให้ไปที่สั้นกว่าเสมอ


2
ใช่foo?.SomeDouble.HasValueเป็นข้อผิดพลาดเวลารวบรวม (ไม่ได้เป็น "โยน" ในคำศัพท์ของฉัน) ในบริบทว่าเพราะชนิดของมันคือไม่เพียงbool? bool(ใน.Whereวิธีการที่ต้องการFunc<Foo, bool>.) มันได้รับอนุญาตให้ทำแน่นอนเนื่องจากว่ามีประเภท(foo?.SomeDouble).HasValue boolนี่คือสิ่งที่บรรทัดแรกของคุณ "แปล" เป็นภาษาภายในโดยคอมไพเลอร์ C # (อย่างน้อยเป็นทางการ)
Jeppe Stig Nielsen

-6

คำตอบทั่วไปและกฎง่ายๆ: ถ้าคุณมีตัวเลือก (เช่นเขียน serializers กำหนดเอง) เพื่อประมวลผล Nullable ในไปป์ไลน์ต่าง ๆ กว่า object- และใช้คุณสมบัติเฉพาะ - ทำและใช้คุณสมบัติเฉพาะ Nullable ดังนั้นจากมุมมองการคิดที่สอดคล้องกันHasValueควรเป็นที่ต้องการ การคิดอย่างสม่ำเสมอสามารถช่วยให้คุณเขียนโค้ดได้ดีขึ้นไม่ต้องเสียเวลาในรายละเอียดมากเกินไป เช่นมีวิธีที่สองจะมีประสิทธิภาพมากกว่าเดิมหลายเท่า (ส่วนใหญ่เป็นเพราะคอมไพเลอร์อินไลน์และมวย แต่ก็ยังมีจำนวนที่แสดงออกมาก):

public static bool CheckObjectImpl(object o)
{
    return o != null;
}

public static bool CheckNullableImpl<T>(T? o) where T: struct
{
    return o.HasValue;
}

การทดสอบเกณฑ์มาตรฐาน:

BenchmarkDotNet=v0.10.5, OS=Windows 10.0.14393
Processor=Intel Core i5-2500K CPU 3.30GHz (Sandy Bridge), ProcessorCount=4
Frequency=3233539 Hz, Resolution=309.2587 ns, Timer=TSC
  [Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1648.0
  Clr    : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1648.0
  Core   : .NET Core 4.6.25009.03, 64bit RyuJIT


        Method |  Job | Runtime |       Mean |     Error |    StdDev |        Min |        Max |     Median | Rank |  Gen 0 | Allocated |
-------------- |----- |-------- |-----------:|----------:|----------:|-----------:|-----------:|-----------:|-----:|-------:|----------:|
   CheckObject |  Clr |     Clr | 80.6416 ns | 1.1983 ns | 1.0622 ns | 79.5528 ns | 83.0417 ns | 80.1797 ns |    3 | 0.0060 |      24 B |
 CheckNullable |  Clr |     Clr |  0.0029 ns | 0.0088 ns | 0.0082 ns |  0.0000 ns |  0.0315 ns |  0.0000 ns |    1 |      - |       0 B |
   CheckObject | Core |    Core | 77.2614 ns | 0.5703 ns | 0.4763 ns | 76.4205 ns | 77.9400 ns | 77.3586 ns |    2 | 0.0060 |      24 B |
 CheckNullable | Core |    Core |  0.0007 ns | 0.0021 ns | 0.0016 ns |  0.0000 ns |  0.0054 ns |  0.0000 ns |    1 |      - |       0 B |

รหัสมาตรฐาน:

public class BenchmarkNullableCheck
{
    static int? x = (new Random()).Next();

    public static bool CheckObjectImpl(object o)
    {
        return o != null;
    }

    public static bool CheckNullableImpl<T>(T? o) where T: struct
    {
        return o.HasValue;
    }

    [Benchmark]
    public bool CheckObject()
    {
        return CheckObjectImpl(x);
    }

    [Benchmark]
    public bool CheckNullable()
    {
        return CheckNullableImpl(x);
    }
}

https://github.com/dotnet/BenchmarkDotNetถูกนำมาใช้

ปล . ผู้คนพูดว่าคำแนะนำ "ชอบ HasValue เพราะการคิดอย่างต่อเนื่อง" ไม่เกี่ยวข้องและไร้ประโยชน์ คุณสามารถทำนายประสิทธิภาพของสิ่งนี้ได้หรือไม่?

public static bool CheckNullableGenericImpl<T>(T? t) where T: struct
{
    return t != null; // or t.HasValue?
}

PPSคนยังคงลบ CheckNullableGenericImplแต่ไม่มีใครพยายามที่จะคาดการณ์ผลการดำเนินงานของ และมีคอมไพเลอร์จะไม่ได้ช่วยให้คุณเปลี่ยนด้วย!=null ควรใช้โดยตรงหากคุณสนใจในประสิทธิภาพHasValueHasValue


2
CheckObjectImpl กล่องของคุณเป็นโมฆะในobjectขณะที่CheckNullableImplไม่ได้ใช้มวย ดังนั้นการเปรียบเทียบก็ไม่ได้เปิดเผยมากนัก ไม่เพียง แต่ไม่ใช่ค่าโดยสารเท่านั้น แต่ยังไร้ประโยชน์เพราะตามที่ระบุไว้ในคำตอบที่ยอมรับแล้วคอมไพเลอร์เขียนใหม่!=ไปHasValueแล้วล่ะค่ะ
GSerg

2
ผู้อ่านไม่สนใจธรรมชาติ struct ของNullable<T>, คุณทำ (โดยมวยมันเป็นผลงานobject) เมื่อคุณใช้!= nullกับ nullable ด้านซ้ายไม่มีมวยเกิดขึ้นเนื่องจากการสนับสนุน!=สำหรับ nullables ทำงานในระดับคอมไพเลอร์ มันแตกต่างกันเมื่อคุณซ่อน nullable objectจากคอมไพเลอร์โดยมวยครั้งแรกที่มันเข้า ไม่ว่าCheckObjectImpl(object o)เกณฑ์มาตรฐานของคุณจะไม่มีเหตุผลก็ตาม
GSerg

3
ปัญหาของฉันคือฉันใส่ใจเกี่ยวกับคุณภาพของเนื้อหาในเว็บไซต์นี้ สิ่งที่คุณโพสต์อาจทำให้เข้าใจผิดหรือผิด ถ้าคุณกำลังพยายามที่จะตอบคำถามของ OP แล้วคำตอบของคุณคือแบนออกผิดปกติซึ่งเป็นเรื่องง่ายที่จะพิสูจน์โดยการเปลี่ยนโทรไปCheckObjectImplกับร่างกายภายในCheckObjectภายในอย่างไรก็ตามความคิดเห็นล่าสุดของคุณแสดงให้เห็นว่าในความเป็นจริงคุณมีคำถามที่แตกต่างอย่างสิ้นเชิงเมื่อคุณตัดสินใจที่จะตอบคำถามอายุ 8 ปีซึ่งทำให้คำตอบของคุณทำให้เข้าใจผิดในบริบทของคำถามเดิม มันไม่ใช่สิ่งที่ OP ถาม
GSerg

3
ใส่ตัวเองในรองเท้าของผู้ชายถัดไปที่ what is faster != or HasValueGoogles เขามาถึงคำถามนี้อ่านคำตอบของคุณชื่นชมมาตรฐานของคุณและพูดว่า "ไม่ฉันไม่เคยใช้!=เพราะเห็นได้ชัดว่าช้ากว่ามาก!" นั่นเป็นข้อสรุปที่ผิดมากซึ่งเขาจะดำเนินการต่อไป นั่นคือเหตุผลที่ฉันเชื่อว่าคำตอบของคุณเป็นอันตราย - มันตอบคำถามที่ผิดและทำให้ข้อสรุปผิดในผู้อ่านที่ไม่สงสัย พิจารณาสิ่งที่เกิดขึ้นเมื่อคุณเปลี่ยนCheckNullableImplไปยังเป็นreturn o != null;คุณจะได้รับผลมาตรฐานเดียวกัน
GSerg

8
ฉันโต้เถียงกับคำตอบของคุณ คำตอบของคุณ deceptively ดูเหมือนว่ามันแสดงให้เห็นถึงความแตกต่างระหว่าง!=และHasValueเมื่อความจริงมันแสดงให้เห็นถึงความแตกต่างระหว่างและobject o T? oถ้าคุณทำในสิ่งที่ผมแนะนำคือว่าเขียนCheckNullableImplเป็นpublic static bool CheckNullableImpl<T>(T? o) where T: struct { return o != null; }คุณจะจบลงด้วยมาตรฐานที่แสดงให้เห็นอย่างชัดเจนว่าเป็นได้ช้ากว่า!= !=ซึ่งควรนำคุณไปสู่ข้อสรุปว่าปัญหาคำตอบของคุณอธิบายไม่เกี่ยวกับ!=vs HasValueเลย
GSerg
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.