در C#، از null برای نشان دادن عدم وجود مقدار استفاده میشود. نوع تهیپذیر نوعی است که مقادیر null را میپذیرد.
پیش از C# ۸.۰، نوعهای ارجاعی همیشه تهیپذیر بودند و نوعهای مقداری نبودند. یک نوع مقداری را میتوان با افزودن یک علامت سؤال (?) به آن، تهیپذیر کرد.
string nullableReferenceType = "hello";
nullableReferenceType = null; // Valid as type is nullable
int nonNullableValueType = 5;
nonNullableValueType = null; // Compile error as type is not nullable
int? nullableValueType = 5; // Define nullable value type
nullableValueType = null; // Valid as type is nullable
دسترسی به عضو متغیری که null است باعث خطای کامپایل نمیشود، اما باعث میشود که NullReferenceException در زمان اجرا پرتاب شود:
string sentence = null;
// Throws NullReferenceException at runtime
sentence.Length;
برای مقابله با این اشتباه رایج، C# ۸ به شما این امکان را میدهد که ویژگیای را انتخاب کنید که نوعهای ارجاعی را بهطور پیشفرض غیرتهیپذیر میکند:
string nonNullableReferenceType = "book";
nonNullableReferenceType = null; // Compile warning (no error!)
string? nullableReferenceType = "movie";
nullableReferenceType = null; // Valid as type is nullable
برای کار ایمن با مقادیر تهیپذیر، پیش از استفاده از آنها بررسی کنید که null هستند یا نه:
string NormalizedName(string? name)
{
if (name == null)
{
return "UNKNOWN";
}
// Value is not null at this point, so no compile warning
// and no runtime NullReferenceException being thrown
return name.ToUpper();
}
NormalizedName(null); // => "UNKNOWN"
NormalizedName("Elisabeth"); // => "ELISABETH"
عملگر ?? به شما امکان میدهد وقتی مقدار null است، یک مقدار پیشفرض برگردانید:
string? name1 = "John";
name1 ?? "Paul"; // => "John"
string? name2 = null;
name2 ?? "George"; // => "George"
عملگر ?. به شما امکان میدهد اعضای یک مقدار را که ممکن است null باشد، بهصورت ایمن فراخوانی کنید:
string? fruit = "apple";
fruit?.Length; // => 5
string? vegetable = null;
vegetable?.Length; // => null
در این تمرین کدی مینویسید که نشان کارمندان کارخانه را چاپ کند.
کارمندان یک شناسه، یک اسم و یک اسم بخش دارند. برچسبهای نشان کارمندان به این شکل قالببندی میشوند: "[id] - name - DEPARTMENT". متد (static) Badge.Print() را پیادهسازی کنید تا برچسب نشان یک کارمند را برگرداند:
Badge.Print(734, "Ernest Johnny Payne", "Strategic Communication");
// => "[734] - Ernest Johnny Payne - STRATEGIC COMMUNICATION"
توجه کنید که اسم بخش روی برچسب باید با حروف بزرگ نوشته شود.
به دلیل یک ایراد عجیب در سیستم رایانهای، کارمندان تازه گاهی وقتی کار در کارخانه را شروع میکنند هنوز شناسه ندارند. چون نشان الزامی است، یک نشان موقت بدون پیشوند شناسه دریافت میکنند. متد (static) Badge.Print() را تغییر دهید تا از کارمندان تازهای که هنوز شناسه ندارند پشتیبانی کند:
Badge.Print(id: null, "Jane Johnson", "Procurement");
// => "Jane Johnson - PROCUREMENT"
حتی مالک کارخانه هم باید همیشه نشان بپوشد. با این حال، مالک بخشی ندارد. در این حالت، برچسب باید به جای اسم بخش، "OWNER" را چاپ کند. متد (static) Badge.Print() را تغییر دهید تا برچسب مالک را چاپ کند:
Badge.Print(254, "Charlotte Hale", department: null);
// => "[254] - Charlotte Hale - OWNER"
توجه کنید که ممکن است مالک هم کارمند تازه باشد:
Badge.Print(id: null, "Charlotte Hale", department: null);
// => "Charlotte Hale - OWNER"