آموزش جامع bool.TryParse() در C# و .NET با مثالهای عملی
بازگشت به راهنمای جامع متدهای TryParse در سیشارپ؛ این مقاله بهصورت مستقل تمام جنبههای bool.TryParse() را از سطح مقدماتی تا نکات حرفهای بررسی میکند.
bool.TryParse() برای تبدیل امن متن به مقدار منطقی به کار میرود و در سناریوهایی مانند تنظیمات روشن و خاموش، Feature Flag و گزینههای فرم مانع تبدیل خطای قابل انتظار به استثنای کنترلی میشود. طراحی درست فقط فراخوانی متد نیست؛ باید قرارداد ورودی، مرز نوع، فرهنگ، خطای کاربر و اعتبار دامنه نیز مشخص باشد.
دامنه یا قرارداد اصلی این نوع دو مقدار منطقی true و false است. مقادیر 1، 0، yes و no بهصورت مستقیم پذیرفته نمیشوند و باید با قرارداد مشخص نرمال شوند. به همین دلیل نتیجه true صرفاً موفقیت تبدیل نحوی را نشان میدهد و مجاز بودن مقدار برای عملیات جاری باید در مرحله بعد بررسی شود.
قاعده کلیدی: مقدار result را فقط زمانی مصرف کنید که مقدار بازگشتی TryParse برابر true باشد؛ مقدار پیشفرض در مسیر شکست یک داده تأییدشده نیست.
تعریف، امضا و قرارداد خروجی
در الگوی TryParse، ورودی بررسی و نتیجه از طریق پارامتر out برگردانده میشود. خروجی متد یک bool برای اعلام موفقیت است و مقدار تبدیلشده در پارامتر out قرار میگیرد. این قرارداد برای مرزهای غیرقابلاعتماد، مانند فرم و فایل، خوانا است و مسیر شکست را به بخش عادی منطق برنامه تبدیل میکند.
امضاهای مهم
bool.TryParse(string? value, out bool result);
bool.TryParse(ReadOnlySpan<char> value, out bool result);
| جزء | نقش | نکته حرفهای |
|---|
| ورودی | رشته یا Span حاوی مقدار | null، قالب و دامنه را بر اساس قرارداد بررسی کنید |
| result | مقدار تبدیلشده | فقط پس از موفقیت معتبر است |
| مقدار بازگشتی | true یا false | مسیر کنترل اصلی اعتبارسنجی است |
| Culture و Style | قواعد تفسیر | در نوعهای حساس صریح تعیین شوند |
تحلیل فنی و طراحی صحیح
استفاده حرفهای از bool.TryParse() با تشخیص مرز اعتماد آغاز میشود. متنی که کاربر، فایل CSV، پارامتر URL یا سامانه بیرونی تولید کرده است میتواند خالی، ناسازگار یا مخرب باشد. TryParse یک سد نحوی فراهم میکند، اما طول ورودی، قواعد دامنه، مجوز دسترسی و ارتباط مقدار با سایر فیلدها همچنان باید کنترل شود.
در حوزه تنظیمات روشن و خاموش، Feature Flag و گزینههای فرم باید میان «قابل تبدیل بودن» و «قابل پذیرش بودن» فرق گذاشت. ممکن است متن بهدرستی تبدیل شود اما مقدار خارج از بازه سیاست سازمان، شناسه ناشناخته یا تاریخ غیرمجاز باشد. این جداسازی پیام خطای دقیقتر، آزمون واحد سادهتر و تغییر قواعد کسبوکار بدون دستکاری Parser را ممکن میکند.
در API بهتر است خطای تبدیل به پاسخ ساختیافته شامل نام فیلد و کد خطا تبدیل شود. در Import نیز ردیفهای خراب را همراه شماره خط و دلیل رد در گزارش جدا نگه دارید. حذف خاموش خطاها ممکن است جمع گزارش یا تصمیم مدیریتی را تحریف کند؛ بنابراین شاخص کیفیت داده بخشی از خروجی فرایند است.
Culture باید از قرارداد واقعی داده بیاید. فایل ماشینی معمولاً با InvariantCulture و قالب ثابت امنتر است، درحالیکه فرم محلی باید فرهنگ انتخابشده کاربر را به کار گیرد. اتکا به CurrentCulture سرور میتواند پس از جابهجایی محیط، بهروزرسانی کانتینر یا اجرای تست روی رایانه دیگر نتیجه را تغییر دهد.
از نظر امنیت، bool.TryParse() تنها تبدیل را انجام میدهد و جای اعتبارسنجی مجوز، محدودیت طول، Allowlist یا کنترل وجود رکورد را نمیگیرد. برای تنظیمات روشن و خاموش، Feature Flag و گزینههای فرم ورودی بسیار طولانی را پیش از پردازش محدود کنید، اطلاعات حساس را در لاگ ننویسید و پیام داخلی استثنا را مستقیماً به کاربر نشان ندهید.
از نظر نگهداری، بهتر است فراخوانیهای تکراری در Parser یا Value Object دامنهای متمرکز شوند. آن جزء میتواند Culture، بازه مجاز، پیامهای فارسی و انگلیسی و سیاست null را یکسان کند. پراکندگی تبدیل در کنترلر، فرم و Repository معمولاً به رفتارهای متفاوت و رفع اشکال دشوار منجر میشود.
مثالهای عملی گامبهگام
ده مثال زیر از تبدیل پایه آغاز میشوند و به سناریوهای مجموعهداده، null، مرز، خطای Culture و کارایی میرسند. هر مثال برای bool.TryParse() طراحی شده و نتیجه نمونه را بدون نیاز به اجرای اولیه نشان میدهد.
مثال شماره 1: خواندن مقدار true
یک مقدار متنی استاندارد از تنظیمات دریافت میشود. bool.TryParse بدون پرتاب استثنا موفقیت را اعلام میکند و فقط در شاخه موفقیت مقدار منطقی مصرف میشود.
using System;
internal static class Program
{
private static void Main()
{
string input = "true";
bool success = bool.TryParse(input, out bool enabled);
Console.WriteLine($"success={success}; enabled={enabled}");
}
}
| شاخص خروجی | نتیجه نمونه |
|---|
| موفقیت | True |
| مقدار | True |
رشتههای استاندارد True و False بدون حساسیت به بزرگی حروف پذیرفته میشوند. برای خوانایی قرارداد بهتر است تولیدکننده تنظیمات همین واژگان را استفاده کند.
مثال شماره 2: پردازش چند Feature Flag
یک سامانه ممکن است چند پرچم قابلیت را از فایل یا متغیر محیطی بخواند. رکورد نامعتبر نباید باعث فعال شدن ناخواسته قابلیت شود و باید جداگانه گزارش گردد.
using System;
internal static class Program
{
private static void Main()
{
string[] flags = { "true", "FALSE", "invalid", " true " };
int valid = 0;
foreach (string text in flags)
{
if (bool.TryParse(text, out bool value))
{
valid++;
Console.WriteLine(value);
}
}
Console.WriteLine($"valid={valid}");
}
}
| شاخص خروجی | نتیجه نمونه |
|---|
| مقادیر معتبر | 3 |
| نامعتبر | 1 |
Whitespace ابتدا و انتها و تفاوت حروف مدیریت میشود، اما واژه خارج از قرارداد false بازگشتی تولید میکند. مقدار خروجی در شکست نباید معیار تصمیم باشد.
مثال شماره 3: Projection برای ViewModel
در رابط کاربری میتوان نتیجه تبدیل را Nullable نگه داشت تا «false واقعی» از «متن نامعتبر» قابل تشخیص باشد. این تفاوت برای نمایش خطای فیلد ضروری است.
using System;
internal static class Program
{
private static void Main()
{
string[] raw = { "true", "bad", "false" };
bool?[] values = Array.ConvertAll(
raw,
text => bool.TryParse(text, out bool value) ? value : null
);
foreach (bool? value in values)
{
Console.WriteLine(value.HasValue ? value.ToString() : "نامعتبر");
}
}
}
| شاخص خروجی | نتیجه نمونه |
|---|
| ترتیب | True | نامعتبر | False |
استفاده از bool? یک مدل ساده است. در فرم حرفهای بهتر است پیام، نام فیلد و متن خام نیز در شیء نتیجه اعتبارسنجی نگهداری شود.
مثال شماره 4: فیلتر قابلیتهای فعال
پس از تبدیل میتوان فقط نام قابلیتهایی را نگه داشت که هم قالب معتبر دارند و هم مقدارشان true است. این کار مشابه شرط WHERE روی دادههای تنظیمات است.
using System;
using Collections.Generic;
using Linq;
internal static class Program
{
private static void Main()
{
var settings = new Dictionary<string, string>
{
["SearchV2"] = "true",
["NewCheckout"] = "false",
["Audit"] = "bad"
};
var active = settings
.Where(item => bool.TryParse(item.Value, out bool value) && value)
.Select(item => item.Key);
Console.WriteLine(string.Join(", ", active));
}
}
| شاخص خروجی | نتیجه نمونه |
|---|
| قابلیت فعال | SearchV2 |
نامعتبر بودن Audit با false بودن NewCheckout یکسان نیست. در سامانه عملیاتی برای مقدار نامعتبر هشدار پیکربندی ثبت کنید تا خطای تایپی پنهان نماند.
مثال شماره 5: ترکیب دو شرط منطقی
فعال شدن یک عملیات حساس ممکن است به دو ورودی معتبر وابسته باشد. Short-circuit باعث میشود فقط در صورت موفقیت هر دو تبدیل، تصمیم نهایی محاسبه شود.
using System;
internal static class Program
{
private static void Main()
{
string featureText = "true";
string adminText = "false";
bool allowed =
bool.TryParse(featureText, out bool feature) &&
bool.TryParse(adminText, out bool isAdmin) &&
feature && isAdmin;
Console.WriteLine(allowed);
}
}
| شاخص خروجی | نتیجه نمونه |
|---|
| اجازه نهایی | False |
تفکیک موفقیت تبدیل از قانون مجوز اهمیت امنیتی دارد. bool.TryParse بهتنهایی احراز هویت یا مجوزدهی نیست و فقط ورودی متنی را تفسیر میکند.
مثال شماره 6: رفتار با null و رشته خالی
داده اختیاری ممکن است null یا خالی باشد. TryParse هر دو را بدون FormatException رد میکند و برنامه میتواند پیام اعتبارسنجی مناسب برگرداند.
using System;
internal static class Program
{
private static void Main()
{
string? first = null;
string second = string.Empty;
Console.WriteLine(bool.TryParse(first, out bool a));
Console.WriteLine(bool.TryParse(second, out bool b));
}
}
| شاخص خروجی | نتیجه نمونه |
|---|
| null | False |
| رشته خالی | False |
در شکست مقدار out برابر false میشود، اما این false یک داده تأییدشده نیست. همیشه مقدار بازگشتی متد را بررسی کنید.
مثال شماره 7: حروف متفاوت و فاصله
ورودی انسانی ممکن است با فاصله یا حروف ترکیبی نوشته شود. این مثال رفتار استاندارد متد را برای چند شکل رایج نشان میدهد.
using System;
internal static class Program
{
private static void Main()
{
string[] inputs = { "TRUE", " false ", "TrUe" };
foreach (string input in inputs)
{
bool ok = bool.TryParse(input, out bool value);
Console.WriteLine($"{input} => {ok}/{value}");
}
}
}
| شاخص خروجی | نتیجه نمونه |
|---|
| TRUE | True |
| false | False معتبر |
| TrUe | True |
پذیرش بدون حساسیت به حروف راحت است، ولی هنگام ذخیرهسازی بهتر است خروجی استاندارد و یکنواخت تولید شود تا مقایسه و پشتیبانی ساده بماند.
مثال شماره 8: خواندن تنظیمات سازمانی
در این نمونه مقدار اجباری از Dictionary دریافت میشود و نبود کلید از نامعتبر بودن مقدار جدا گزارش میگردد. این تفکیک عیبیابی تنظیمات را سریعتر میکند.
using System;
using Collections.Generic;
internal static class Program
{
private static void Main()
{
var config = new Dictionary<string, string>
{
["EnableCache"] = "true"
};
if (config.TryGetValue("EnableCache", out string? text) &&
bool.TryParse(text, out bool enabled))
{
Console.WriteLine($"cache={enabled}");
}
else
{
Console.WriteLine("تنظیم وجود ندارد یا نامعتبر است");
}
}
}
| شاخص خروجی | نتیجه نمونه |
|---|
| EnableCache | True |
TryGetValue و TryParse هر دو قرارداد بدون استثنا دارند و برای مسیرهای قابل انتظار مناسباند. برای تنظیم حیاتی، شکست باید مانع شروع برنامه یا باعث هشدار جدی شود.
مثال شماره 9: روش اشتباه برای 1 و yes
bool.TryParse قرارداد واژگانی محدود دارد. اگر محصول مقادیر 1، 0، yes و no را میپذیرد، باید نرمالسازی صریح و قابل آزمون نوشته شود.
using System;
internal static class Program
{
private static void Main()
{
string input = "yes";
bool direct = bool.TryParse(input, out bool directValue);
bool normalized = input.Trim().ToLowerInvariant() switch
{
"yes" or "1" => true,
"no" or "0" => false,
_ => throw new ArgumentException("مقدار منطقی نامعتبر")
};
Console.WriteLine($"direct={direct}; normalized={normalized}");
}
}
| شاخص خروجی | نتیجه نمونه |
|---|
| تبدیل مستقیم | False |
| پس از قرارداد سفارشی | True |
نرمالسازی را در یک نقطه مشترک قرار دهید؛ افزودن تفسیرهای پراکنده در فرمها و سرویسها باعث ناسازگاری و خطای نگهداری میشود.
مثال شماره 10: استفاده از ReadOnlySpan
در Parser پرتکرار میتوان بخش متن را بدون ساخت رشته جدید به overload مبتنی بر Span داد. هدف کاهش تخصیص حافظه در مسیر داغ است.
using System;
internal static class Program
{
private static void Main()
{
ReadOnlySpan<char> token = "false".AsSpan();
bool success = bool.TryParse(token, out bool value);
Console.WriteLine($"success={success}; value={value}");
}
}
| شاخص خروجی | نتیجه نمونه |
|---|
| موفقیت | True |
| مقدار | False |
برای چند فیلد فرم، این بهینهسازی ضروری نیست. ابتدا با پروفایلر گلوگاه را پیدا کنید و سپس Span را در Parserهای حجیم بهکار ببرید.
خطاهای رایج و راه اصلاح
- استفاده از result بدون بررسی مقدار بازگشتی؛ اصلاح: منطق مصرف مقدار را داخل شاخه موفقیت قرار دهید.
- یکی گرفتن مقدار پیشفرض با شکست؛ اصلاح: وضعیت تبدیل را همراه مقدار نگه دارید یا Result صریح بسازید.
- اتکا به فرهنگ سرور؛ اصلاح: Culture و Style را از قرارداد داده تعیین کنید.
- پذیرش هر مقدار قابل تبدیل؛ اصلاح: پس از تبدیل، بازه، Allowlist و قواعد ارتباطی دامنه را بررسی کنید.
- حذف خاموش رکورد خراب در Import؛ اصلاح: شمارش و گزارش خطا را در خروجی فرایند قرار دهید.
- نادیده گرفتن نکته اختصاصی نوع؛ اصلاح: مقادیر 1، 0، yes و no بهصورت مستقیم پذیرفته نمیشوند و باید با قرارداد مشخص نرمال شوند.
پیام خطا باید قابل اقدام باشد. بهجای «ورودی نامعتبر است» میتوان قالب مورد انتظار، محدوده مجاز و یک نمونه صحیح را ارائه کرد. بااینحال جزئیات داخلی، Stack Trace یا داده حساس نباید در پاسخ عمومی ظاهر شود.
کارایی، تخصیص حافظه و Best Practice
TryParse برای شکست قابل انتظار از الگوی Parse همراه try/catch مناسبتر است، زیرا استثنا برای کنترل جریان عادی طراحی نشده است. این حکم به معنی ممنوع بودن Parse نیست؛ اگر رشته یک ثابت داخلی معتبر است و خرابی آن باگ برنامه محسوب میشود، fail-fast با Parse میتواند انتخاب روشنی باشد.
overloadهای ReadOnlySpan در Parserهای پرتکرار امکان کار روی برشی از بافر را بدون ساخت substring میدهند. سود آن در فایلهای بزرگ، پروتکل یا پردازش میلیونها توکن بیشتر است. در فرم عادی، پیچیدگی اضافی ممکن است ارزش نداشته باشد؛ ابتدا CPU، Allocation و نرخ شکست را اندازهگیری کنید.
برای آزمون، حداقل حالتهای معتبر، null، خالی، فاصله، Culture متفاوت، کمینه، بیشینه، خارج از محدوده و مقدار معتبر ولی غیرمجاز را پوشش دهید. تستها باید Target Framework واقعی را اجرا کنند، زیرا برخی overloadها و رفتارهای گوشهای میان نسخههای .NET تفاوت دارند.
سؤالات متداول
پرسش 1: bool.TryParse() دقیقاً چه مسئلهای را حل میکند؟
bool.TryParse() متن را با قرارداد نوع مقصد بررسی میکند و بدون تبدیل شکست قابل انتظار به استثنا، وضعیت موفقیت را برمیگرداند. این ویژگی در ورودی کاربر، فایل، API و تنظیمات ارزشمند است. حوزه رایج این مقاله تنظیمات روشن و خاموش، Feature Flag و گزینههای فرم است، اما اعتبار نحوی فقط نخستین مرحله است و قواعد دامنه باید جدا اعمال شوند.
پرسش 2: در صورت شکست bool.TryParse() چه اتفاقی برای result میافتد؟
متد false برمیگرداند و result مقدار پیشفرض نوع را خواهد داشت یا نباید معتبر فرض شود. الگوی درست این است که result فقط در شاخه true مصرف شود. تکیه بر صفر، false، تاریخ کمینه یا Guid.Empty میتواند داده نامعتبر را با یک مقدار واقعی اشتباه بگیرد و خطای خاموش ایجاد کند.
پرسش 3: Culture چه اثری بر bool.TryParse() دارد؟
اثر Culture به نوع بستگی دارد. اعداد اعشاری، جداکننده هزارگان و تاریخ به فرهنگ حساساند، درحالیکه Guid و bool قرارداد محدودتری دارند. در مرزهای ماشینی CultureInfo.InvariantCulture و قالب مستند، و در رابط کاربر فرهنگ انتخابشده کاربر مناسب است. فرهنگ سرور نباید بهطور تصادفی نتیجه را تعیین کند.
پرسش 4: چگونه bool.TryParse() را در نرمافزار تجاری استفاده کنیم؟
یک لایه اعتبارسنجی بسازید که متن خام، نتیجه تبدیل، کد خطا و پیام قابل فهم را برگرداند. سپس قانون کسبوکار مربوط به تنظیمات روشن و خاموش، Feature Flag و گزینههای فرم را اعمال کنید. این جداسازی هم تستپذیری را بالا میبرد و هم امکان گزارش کیفیت داده، مشاوره فنی و توسعه سفارشی جریان Import را فراهم میکند.
پرسش 5: آیا جایگزینی بهتر از bool.TryParse() وجود دارد؟
پاسخ به قرارداد ورودی وابسته است. برای قالب ثابت TryParseExact، برای دادهای که خرابی آن باگ است Parse، و برای تبدیلهای سفارشی یک Value Object یا Parser دامنهای مناسبتر است. هدف انتخاب کوتاهترین کد نیست؛ باید خطا، Culture، سازگاری نسخه و پیام کاربر بهروشنی مدیریت شود.
پرسش 6: برای پیادهسازی سازمانی bool.TryParse() چه خدماتی لازم میشود؟
در پروژه بزرگ معمولاً طراحی قرارداد داده، اعتبارسنجی چندلایه، تست مرزی، ثبت خطای امن، داشبورد کیفیت ورودی و پایش لازم است. تیم توسعه یا مشاور میتواند این اجزا را متناسب با معماری C# و .NET، حجم داده و الزامات امنیتی پیاده کند. خود متد کوچک است، اما فرایند قابل اعتماد پیرامون آن اهمیت اصلی را دارد.
پرسش 7: خطای رایج هنگام کار با bool.TryParse() چیست؟
رایجترین خطا استفاده از result بدون بررسی مقدار بازگشتی است. خطاهای دیگر شامل اتکا به Culture جاری، نادیده گرفتن مرز نوع، یکی گرفتن اعتبار نحوی و معنایی و حذف خاموش رکورد نامعتبر است. نکته اختصاصی این موضوع نیز چنین است: مقادیر 1، 0، yes و no بهصورت مستقیم پذیرفته نمیشوند و باید با قرارداد مشخص نرمال شوند.
پرسش 8: کارایی bool.TryParse() در پردازش حجیم چگونه است؟
در شکستهای قابل انتظار، TryParse معمولاً از کنترل جریان با exception مناسبتر است. overloadهای ReadOnlySpan میتوانند تخصیص substring را کاهش دهند. بااینحال نتیجه به نسخه .NET، الگوی داده و مسیر اجرا وابسته است؛ پروفایلر و BenchmarkDotNet باید تصمیم را تأیید کنند و بهینهسازی زودهنگام نباید خوانایی را قربانی کند.
پرسش 9: بهترین روش طراحی با bool.TryParse() چیست؟
قرارداد ورودی را مستند کنید، Culture و Style را در صورت نیاز صریح بدهید، result را فقط پس از true مصرف کنید، اعتبار دامنه را جدا بسنجید و خطا را با پیام قابل اقدام گزارش دهید. برای تنظیمات روشن و خاموش، Feature Flag و گزینههای فرم آزمونهای مرزی، null، مقدار نامعتبر، ورودی بسیار بزرگ و سناریوی واقعی کسبوکار را در مجموعه تست قرار دهید.
پرسش 10: bool.TryParse() با کدام نسخههای C# و .NET سازگار است؟
overload پایه string در نسخههای قدیمی .NET نیز در دسترس است، اما overloadهای Span، UTF-8 و رابطهای Generic Math در نسخههای جدیدتر افزوده شدهاند. پروژه باید مستندات Target Framework خود را مبنا قرار دهد. اگر کتابخانه چندهدفه است، API سطح مشترک را انتخاب یا برای نسخههای جدید مسیر بهینه جدا تعریف کنید.
سؤالات مصاحبه C# و .NET
پرسشهای زیر دانش قراردادی و معماری داوطلب را میسنجند، نه صرفاً حفظ کردن امضای متد.
- تفاوت قرارداد خطای bool.TryParse() با Parse را توضیح دهید و برای هر کدام یک سناریو نام ببرید.
- چرا بررسی مقدار بازگشتی قبل از result ضروری است و مقدار پیشفرض چه خطری دارد؟
- اثر Culture، Style یا قالب ورودی بر bool.TryParse() را با یک مثال تشریح کنید.
- اعتبار نحوی و اعتبار کسبوکار در موضوع تنظیمات روشن و خاموش، Feature Flag و گزینههای فرم چگونه از هم جدا میشوند؟
- چه زمانی overload مبتنی بر ReadOnlySpan ارزشمند است و چگونه سود آن را اندازه میگیرید؟
چکلیست نهایی
- نوع مقصد و محدوده آن با دامنه واقعی داده سازگار است.
- Culture، Style یا قالب ثابت در مرز سیستم مشخص شده است.
- result فقط در مسیر موفقیت مصرف میشود.
- اعتبار نحوی از قواعد کسبوکار جداست.
- null، مقدار خالی، مرز و ورودی خراب تست شدهاند.
- خطاها قابل پایشاند و داده حساس در لاگ قرار نمیگیرد.
- بهینهسازی Span تنها پس از اندازهگیری انجام شده است.
جمعبندی
bool.TryParse() ابزار کوچکی برای ساخت مرز ورودی قابل اعتماد است. ارزش واقعی آن زمانی دیده میشود که قرارداد فرهنگ، محدوده، گزارش خطا و اعتبار دامنه پیرامونش درست طراحی شود. در تنظیمات روشن و خاموش، Feature Flag و گزینههای فرم همین رویکرد از داده خاموش اشتباه، استثناهای پرتکرار و اختلاف رفتار محیطها جلوگیری میکند.
برای مرور سایر نوعها و انتخاب API مناسب، راهنمای جامع همه متدهای TryParse در C# و .NET را مطالعه کنید.