มีสองประเด็นที่นี่: 1) การทดสอบเพื่อดูว่าประเภทเป็นโมฆะ; และ 2) การทดสอบเพื่อดูว่าวัตถุแสดงถึงประเภท nullable
สำหรับปัญหา 1 (ทดสอบประเภท) นี่เป็นวิธีแก้ปัญหาที่ฉันใช้ในระบบของฉันเอง: TypeIsNullable-check solution
สำหรับปัญหา 2 (ทดสอบวัตถุ) โซลูชันของ Dean Chalk ด้านบนใช้งานได้กับประเภทค่า แต่มันไม่ทำงานสำหรับประเภทอ้างอิงเนื่องจากการใช้ <T> เกินพิกัดจะส่งคืนค่าเท็จเสมอ เนื่องจากประเภทการอ้างอิงนั้นเป็นโมฆะโดยเนื้อแท้การทดสอบประเภทการอ้างอิงจึงควรกลับมาจริง โปรดดูหมายเหตุ [เกี่ยวกับ "ความไร้ผล"] ด้านล่างสำหรับคำอธิบายของความหมายเหล่านี้ ดังนั้นนี่คือการแก้ไขแนวทางของ Dean:
public static bool IsObjectNullable<T>(T obj)
{
// If the parameter-Type is a reference type, or if the parameter is null, then the object is always nullable
if (!typeof(T).IsValueType || obj == null)
return true;
// Since the object passed is a ValueType, and it is not null, it cannot be a nullable object
return false;
}
public static bool IsObjectNullable<T>(T? obj) where T : struct
{
// Always return true, since the object-type passed is guaranteed by the compiler to always be nullable
return true;
}
และนี่คือการแก้ไขรหัสลูกค้าทดสอบของฉันสำหรับการแก้ปัญหาข้างต้น:
int a = 123;
int? b = null;
object c = new object();
object d = null;
int? e = 456;
var f = (int?)789;
string g = "something";
bool isnullable = IsObjectNullable(a); // false
isnullable = IsObjectNullable(b); // true
isnullable = IsObjectNullable(c); // true
isnullable = IsObjectNullable(d); // true
isnullable = IsObjectNullable(e); // true
isnullable = IsObjectNullable(f); // true
isnullable = IsObjectNullable(g); // true
เหตุผลที่ฉันแก้ไขแนวทางของ Dean ใน IsObjectNullable <T> (T t) คือวิธีดั้งเดิมของเขาส่งคืนเท็จเสมอสำหรับประเภทการอ้างอิง เนื่องจากวิธีการเช่น IsObjectNullable ควรสามารถจัดการค่าชนิดการอ้างอิงและเนื่องจากชนิดของการอ้างอิงทั้งหมดเป็นโมฆะโดยเนื้อแท้แล้วถ้าผ่านประเภทการอ้างอิงหรือเป็นโมฆะวิธีการควรกลับจริง
สองวิธีข้างต้นสามารถแทนที่ด้วยวิธีการเดียวต่อไปนี้และบรรลุผลลัพธ์เดียวกัน:
public static bool IsObjectNullable<T>(T obj)
{
Type argType = typeof(T);
if (!argType.IsValueType || obj == null)
return true;
return argType.IsGenericType && argType.GetGenericTypeDefinition() == typeof(Nullable<>);
}
อย่างไรก็ตามปัญหาของวิธีการเดียววิธีสุดท้ายนี้คือประสิทธิภาพลดลงเมื่อใช้พารามิเตอร์ Nullable <T> ใช้เวลาประมวลผลมากขึ้นในการดำเนินการบรรทัดสุดท้ายของวิธีการเดียวนี้มากกว่าการอนุญาตให้คอมไพเลอร์เลือกวิธีที่สองเกินพิกัดที่แสดงก่อนหน้านี้เมื่อใช้พารามิเตอร์ Nullable <T> -type ในการเรียก IsObjectNullable ดังนั้นทางออกที่ดีที่สุดคือการใช้วิธีสองวิธีที่แสดงไว้ที่นี่
ถ้ำ: วิธีนี้ใช้งานได้อย่างน่าเชื่อถือเฉพาะในกรณีที่ถูกเรียกโดยใช้การอ้างอิงวัตถุดั้งเดิมหรือสำเนาที่แน่นอนดังที่แสดงในตัวอย่าง อย่างไรก็ตามหากวัตถุที่ไม่มีค่าเป็นชนิดอื่น (เช่นวัตถุเป็นต้น) แทนที่จะถูกบรรจุในรูปแบบ Nullable <> ดั้งเดิมวิธีนี้จะไม่สามารถทำงานได้อย่างน่าเชื่อถือ ถ้ารหัสที่เรียกใช้วิธีนี้ไม่ได้ใช้การอ้างอิงวัตถุต้นฉบับที่ไม่มีกล่องหรือสำเนาที่แน่นอนมันไม่สามารถตรวจสอบความถูกต้องของวัตถุได้โดยใช้วิธีนี้
ในสถานการณ์การเขียนโค้ดส่วนใหญ่ในการพิจารณาความสามารถในการลบล้างเราต้องพึ่งพาการทดสอบประเภทของวัตถุดั้งเดิมไม่ใช่การอ้างอิง (เช่นรหัสจะต้องมีการเข้าถึงประเภทดั้งเดิมของวัตถุเพื่อกำหนดความถูกต้อง) ในกรณีที่พบบ่อยเหล่านี้ IsTypeNullable (ดูลิงค์) เป็นวิธีการที่เชื่อถือได้ในการพิจารณาความสามารถในการเป็นโมฆะ
PS - เกี่ยวกับ "nullability"
ฉันควรทำซ้ำคำสั่งเกี่ยวกับความถูกต้องฉันทำในโพสต์แยกซึ่งใช้โดยตรงกับที่อยู่หัวข้อนี้อย่างถูกต้อง นั่นคือฉันเชื่อว่าจุดเน้นของการอภิปรายที่นี่ไม่ควรเป็นวิธีการตรวจสอบเพื่อดูว่าวัตถุเป็นชนิด Nullable ทั่วไปหรือไม่ แต่จะว่าใครสามารถกำหนดค่า null ให้กับวัตถุประเภทนั้น ในคำอื่น ๆ ฉันคิดว่าเราควรจะกำหนดว่าประเภทวัตถุเป็นโมฆะไม่ว่าจะเป็นโมฆะ ความแตกต่างในความหมายคือเหตุผลที่เป็นประโยชน์ในการกำหนดความไร้ซึ่งมักเป็นเรื่องที่
ในระบบที่ใช้ออบเจ็กต์ที่มีชนิดที่ไม่รู้จักจนกระทั่งถึงเวลาใช้งาน (บริการบนเว็บการโทรทางไกลฐานข้อมูลฟีดและอื่น ๆ ) ข้อกำหนดทั่วไปคือการพิจารณาว่า null สามารถกำหนดให้กับวัตถุหรืออาจมีวัตถุ เป็นโมฆะ การดำเนินการดังกล่าวกับประเภทที่ไม่เป็นโมฆะอาจทำให้เกิดข้อผิดพลาดซึ่งมักจะมีข้อยกเว้นซึ่งมีราคาแพงมากทั้งในแง่ของประสิทธิภาพและความต้องการการเข้ารหัส ในการใช้แนวทางที่เป็นที่ต้องการอย่างสูงในการหลีกเลี่ยงปัญหาดังกล่าวจำเป็นต้องพิจารณาว่าวัตถุประเภทใด ๆ ที่มีความสามารถในการบรรจุโมฆะหรือไม่ นั่นคือไม่ว่าจะเป็น 'nullable' โดยทั่วไป
ในทางปฏิบัติและโดยทั่วไปแล้วความสามารถในการลบล้างใน. NET นั้นไม่ได้หมายความว่าประเภทของวัตถุนั้นเป็นรูปแบบของความว่างเปล่า ในความเป็นจริงหลาย ๆ กรณีวัตถุมีประเภทอ้างอิงสามารถมีค่าเป็นโมฆะและทำให้เป็นโมฆะทั้งหมด; สิ่งเหล่านี้ไม่มีประเภทที่เป็นโมฆะ ดังนั้นเพื่อจุดประสงค์ในทางปฏิบัติในสถานการณ์ส่วนใหญ่การทดสอบควรทำสำหรับแนวคิดทั่วไปเกี่ยวกับความไร้ประสิทธิภาพและแนวคิดที่ขึ้นกับการนำไปปฏิบัติของ Nullable ดังนั้นเราไม่ควรวางสายโดยเน้นที่. NET Nullable แต่เพียงอย่างเดียว แต่รวมความเข้าใจของเราเกี่ยวกับข้อกำหนดและพฤติกรรมในกระบวนการของการมุ่งเน้นที่แนวคิดทั่วไปที่ใช้งานได้จริง