مثالهای عملی مستقل
مثالها از تبدیل پایه شروع میشوند و به داده دستهای، null، مقدار مرزی، خطای کنترلشده و مسیر بهینه میرسند. هر نمونه یک برنامه کامل کنسولی است و خروجی نمایشی اجازه میدهد نتیجه را بدون اجرای فوری کد بررسی کنید.
مثال 1: اندازهگیری مسیر موفق Parse
در این آزمون یک مقدار معتبر بارها با Parse تبدیل میشود تا هزینه پایه تبدیل، بدون ورود به مسیر استثنا، دیده شود.
using System;
using System.Diagnostics;
public static class Program
{
public static void Main()
{
const string text = "123456";
const int iterations = 200_000;
var watch = System.Diagnostics.Stopwatch.StartNew();
long sum = 0;
for (int i = 0; i < iterations; i++)
{
sum += int.Parse(text);
}
watch.Stop();
Console.WriteLine($"Sum={sum}; ElapsedMs={watch.ElapsedMilliseconds}");
}
}
| ورودی یا سناریو | خروجی نمونه | نکته |
|---|
| 123456 | جمع قابل پیشبینی و زمان وابسته به سختافزار | اندازهگیری مسیر موفق Parse |
کاربرد عملی این الگو در مسیرهای پرترافیک، ورودی کاربر، فایلهای حجیم، APIها و پردازش دستهای دیده میشود. در نسخه تولیدی، پیام خطا، ثبت رخداد، حریم خصوصی داده و تست واحد را متناسب با قرارداد سامانه تکمیل کنید.
مثال 2: اندازهگیری مسیر موفق TryParse
همان بار کاری با TryParse اجرا میشود. در ورودیهای کاملاً معتبر اختلاف معمولاً کوچک است و نتیجه باید با اندازهگیری واقعی قضاوت شود.
using System;
using System.Diagnostics;
public static class Program
{
public static void Main()
{
const string text = "123456";
const int iterations = 200_000;
var watch = System.Diagnostics.Stopwatch.StartNew();
long sum = 0;
for (int i = 0; i < iterations; i++)
{
if (int.TryParse(text, out int value))
{
sum += value;
}
}
watch.Stop();
Console.WriteLine($"Sum={sum}; ElapsedMs={watch.ElapsedMilliseconds}");
}
}
| ورودی یا سناریو | خروجی نمونه | نکته |
|---|
| 123456 | جمع یکسان با Parse و زمان قابل مقایسه | اندازهگیری مسیر موفق TryParse |
کاربرد عملی این الگو در مسیرهای پرترافیک، ورودی کاربر، فایلهای حجیم، APIها و پردازش دستهای دیده میشود. در نسخه تولیدی، پیام خطا، ثبت رخداد، حریم خصوصی داده و تست واحد را متناسب با قرارداد سامانه تکمیل کنید.
مثال 3: هزینه استثنا برای داده نامعتبر
این مثال عمداً داده نامعتبر را وارد Parse میکند. ساخت و پرتاب FormatException در حلقه داغ هزینه CPU و تخصیص حافظه را بهطور محسوسی افزایش میدهد.
using System;
public static class Program
{
public static void Main()
{
string[] values = { "10", "bad", "30", "?", "50" };
int failures = 0;
foreach (string text in values)
{
try
{
_ = int.Parse(text);
}
catch (FormatException)
{
failures++;
}
}
Console.WriteLine($"Failures={failures}");
}
}
| ورودی یا سناریو | خروجی نمونه | نکته |
|---|
| 123456 | Failures=2 | هزینه استثنا برای داده نامعتبر |
کاربرد عملی این الگو در مسیرهای پرترافیک، ورودی کاربر، فایلهای حجیم، APIها و پردازش دستهای دیده میشود. در نسخه تولیدی، پیام خطا، ثبت رخداد، حریم خصوصی داده و تست واحد را متناسب با قرارداد سامانه تکمیل کنید.
مثال 4: مسیر بدون استثنا برای داده نامعتبر
TryParse شکست قابل انتظار را با مقدار false گزارش میکند و از هزینه ایجاد استثنا در مسیر عادی برنامه جلوگیری میکند.
using System;
public static class Program
{
public static void Main()
{
string[] values = { "10", "bad", "30", "?", "50" };
int failures = 0;
foreach (string text in values)
{
if (!int.TryParse(text, out _))
{
failures++;
}
}
Console.WriteLine($"Failures={failures}");
}
}
| ورودی یا سناریو | خروجی نمونه | نکته |
|---|
| 123456 | Failures=2 | مسیر بدون استثنا برای داده نامعتبر |
کاربرد عملی این الگو در مسیرهای پرترافیک، ورودی کاربر، فایلهای حجیم، APIها و پردازش دستهای دیده میشود. در نسخه تولیدی، پیام خطا، ثبت رخداد، حریم خصوصی داده و تست واحد را متناسب با قرارداد سامانه تکمیل کنید.
مثال 5: اندازهگیری تخصیص حافظه همان Thread
متد GetAllocatedBytesForCurrentThread دیدی عملی از تخصیصهای مدیریتشده میدهد. گرمکردن کد و ثابت نگهداشتن ورودی برای کاهش خطای آزمون مهم است.
using System;
public static class Program
{
public static void Main()
{
const string text = "42";
_ = int.TryParse(text, out _);
long before = GC.GetAllocatedBytesForCurrentThread();
for (int i = 0; i < 100_000; i++)
{
_ = int.TryParse(text, out int value);
}
long allocated = GC.GetAllocatedBytesForCurrentThread() - before;
Console.WriteLine($"AllocatedBytes={allocated}");
}
}
| ورودی یا سناریو | خروجی نمونه | نکته |
|---|
| 123456 | مقدار کم و وابسته به نسخه Runtime | اندازهگیری تخصیص حافظه همان Thread |
کاربرد عملی این الگو در مسیرهای پرترافیک، ورودی کاربر، فایلهای حجیم، APIها و پردازش دستهای دیده میشود. در نسخه تولیدی، پیام خطا، ثبت رخداد، حریم خصوصی داده و تست واحد را متناسب با قرارداد سامانه تکمیل کنید.
مثال 6: تبدیل مستقیم ReadOnlySpan
در پردازش بخشی از یک رشته میتوان Span را مستقیماً تبدیل کرد تا ساخت Substring و تخصیص رشته موقت حذف شود.
using System;
public static class Program
{
public static void Main()
{
ReadOnlySpan<char> line = "ID=84521;OK".AsSpan();
ReadOnlySpan<char> idPart = line.Slice(3, 5);
if (int.TryParse(idPart, out int id))
{
Console.WriteLine(id);
}
}
}
| ورودی یا سناریو | خروجی نمونه | نکته |
|---|
| 123456 | 84521 | تبدیل مستقیم ReadOnlySpan |
کاربرد عملی این الگو در مسیرهای پرترافیک، ورودی کاربر، فایلهای حجیم، APIها و پردازش دستهای دیده میشود. در نسخه تولیدی، پیام خطا، ثبت رخداد، حریم خصوصی داده و تست واحد را متناسب با قرارداد سامانه تکمیل کنید.
مثال 7: اثر نرخ خطا بر انتخاب API
دو مجموعه با نرخ خطای متفاوت پردازش میشوند. این الگو نشان میدهد انتخاب Parse یا TryParse باید بر اساس قرارداد و احتمال شکست انجام شود.
using System;
public static class Program
{
public static void Main()
{
string[] values = { "1", "2", "bad", "4", "bad", "6" };
int valid = 0;
int invalid = 0;
foreach (string text in values)
{
if (int.TryParse(text, out _)) valid++;
else invalid++;
}
Console.WriteLine($"Valid={valid}; Invalid={invalid}");
}
}
| ورودی یا سناریو | خروجی نمونه | نکته |
|---|
| 123456 | Valid=4; Invalid=2 | اثر نرخ خطا بر انتخاب API |
کاربرد عملی این الگو در مسیرهای پرترافیک، ورودی کاربر، فایلهای حجیم، APIها و پردازش دستهای دیده میشود. در نسخه تولیدی، پیام خطا، ثبت رخداد، حریم خصوصی داده و تست واحد را متناسب با قرارداد سامانه تکمیل کنید.
مثال 8: فرهنگ ثابت در پردازش سرویس
فرهنگ باید خارج از حلقه و بهصورت صریح انتخاب شود تا تفسیر عدد پایدار بماند و ساخت اشیای تکراری وارد اندازهگیری نشود.
using System;
using System.Globalization;
public static class Program
{
public static void Main()
{
string[] values = { "10.5", "20.25", "30.75" };
var culture = System.Globalization.CultureInfo.InvariantCulture;
double total = 0;
foreach (string text in values)
{
if (double.TryParse(text, System.Globalization.NumberStyles.Float, culture, out double value))
{
total += value;
}
}
Console.WriteLine(total.ToString(culture));
}
}
| ورودی یا سناریو | خروجی نمونه | نکته |
|---|
| 123456 | 61.5 | فرهنگ ثابت در پردازش سرویس |
کاربرد عملی این الگو در مسیرهای پرترافیک، ورودی کاربر، فایلهای حجیم، APIها و پردازش دستهای دیده میشود. در نسخه تولیدی، پیام خطا، ثبت رخداد، حریم خصوصی داده و تست واحد را متناسب با قرارداد سامانه تکمیل کنید.
مثال 9: نمونه اشتباه و نسخه اصلاحشده
گرفتن همه Exceptionها در حلقه هم خطاهای برنامهنویسی را پنهان میکند و هم هزینه مسیر نامعتبر را بالا میبرد. نسخه اصلاحی از TryParse استفاده میکند.
using System;
public static class Program
{
public static void Main()
{
string text = "not-a-number";
// روش اصلاحشده: شکست ورودی یک نتیجه عادی است.
if (!int.TryParse(text, out int value))
{
Console.WriteLine("Invalid input");
}
else
{
Console.WriteLine(value);
}
}
}
| ورودی یا سناریو | خروجی نمونه | نکته |
|---|
| 123456 | Invalid input | نمونه اشتباه و نسخه اصلاحشده |
کاربرد عملی این الگو در مسیرهای پرترافیک، ورودی کاربر، فایلهای حجیم، APIها و پردازش دستهای دیده میشود. در نسخه تولیدی، پیام خطا، ثبت رخداد، حریم خصوصی داده و تست واحد را متناسب با قرارداد سامانه تکمیل کنید.
مثال 10: آزمون منصفانه با Warm-up و چند دور
یک بار اجرا برای نتیجهگیری کافی نیست. نمونه زیر کد را گرم میکند و چند دور مستقل میسنجد؛ برای تصمیم نهایی ابزار BenchmarkDotNet پیشنهاد میشود.
using System;
using System.Diagnostics;
public static class Program
{
public static void Main()
{
const string text = "9001";
_ = int.TryParse(text, out _);
for (int round = 1; round <= 3; round++)
{
var watch = System.Diagnostics.Stopwatch.StartNew();
long sum = 0;
for (int i = 0; i < 100_000; i++)
{
if (int.TryParse(text, out int value)) sum += value;
}
watch.Stop();
Console.WriteLine($"Round={round}; Sum={sum}; Ticks={watch.ElapsedTicks}");
}
}
}
| ورودی یا سناریو | خروجی نمونه | نکته |
|---|
| 123456 | سه خط زمانسنجی با Sum یکسان | آزمون منصفانه با Warm-up و چند دور |
کاربرد عملی این الگو در مسیرهای پرترافیک، ورودی کاربر، فایلهای حجیم، APIها و پردازش دستهای دیده میشود. در نسخه تولیدی، پیام خطا، ثبت رخداد، حریم خصوصی داده و تست واحد را متناسب با قرارداد سامانه تکمیل کنید.
سؤالات متداول
۱. Parse و TryParse از دید کارایی و حافظه دقیقاً چه کاری انجام میدهد؟
Parse و TryParse از دید کارایی و حافظه نمایش متنی معتبر را مطابق قواعد نوع مقصد به یک مقدار نوعدار تبدیل میکند. نتیجه پس از تبدیل میتواند در محاسبه، شرط، ذخیرهسازی یا منطق دامنه استفاده شود و دیگر لازم نیست با رشته خام کار کنیم.
۲. چه زمانی استفاده از Parse و TryParse از دید کارایی و حافظه برای تازهکاران مناسب است؟
وقتی منبع داده مورد اعتماد است، قالب از قبل اعتبارسنجی شده و شکست واقعاً یک وضعیت استثنایی محسوب میشود، Parse انتخابی ساده و خواناست. برای ورودی مستقیم کاربر معمولاً TryParse تجربه مقاومتری ایجاد میکند.
۳. آیا استفاده درست از Parse و TryParse از دید کارایی و حافظه هزینه نگهداری پروژه را کم میکند؟
بله؛ تبدیل در مرز سیستم و انتقال مقدار نوعدار به لایههای داخلی، شرطهای تکراری و خطاهای پنهان را کاهش میدهد. این جداسازی در پروژههای تجاری، گزارشگیری و سامانههای چندلایه ارزش زیادی دارد.
۴. در پروژه سفارشی چگونه سیاست تبدیل Parse و TryParse از دید کارایی و حافظه طراحی میشود؟
قالب ورودی، فرهنگ، رفتار null، محدوده مجاز، پیام خطا و محل ثبت رخداد باید در قرارداد ورودی مشخص شوند. سپس تبدیل در یک نقطه مشترک مانند Validator، Mapper یا لایه ورودی پیادهسازی و با تست پوشش داده میشود.
۵. تفاوت کلیدی Parse و TryParse برای Parse و TryParse از دید کارایی و حافظه چیست؟
Parse در شکست استثنا پرتاب میکند، ولی TryParse با یک مقدار bool موفقیت را گزارش میدهد و خروجی را از پارامتر out تحویل میدهد. تفاوت اصلی در قرارداد شکست است، نه صرفاً شکل نوشتن کد.
۶. برای پیادهسازی حرفهای Parse و TryParse از دید کارایی و حافظه چه خدماتی لازم میشود؟
در سامانه حساس میتوان از بازبینی قرارداد داده، طراحی اعتبارسنجی، تست دادههای مرزی، پروفایل کارایی و ثبت خطای ساختیافته استفاده کرد. مشاوره فنی کمک میکند این تصمیمها با معماری و نیاز واقعی محصول هماهنگ شوند.
۷. خطاهای رایج Parse و TryParse از دید کارایی و حافظه کداماند؟
ارسال null، رشته خالی، قالب ناسازگار، عدد خارج از محدوده، فرهنگ اشتباه و گرفتن کلی همه Exceptionها از خطاهای پرتکرار هستند. ثبت مقدار حساس نیز باید با قواعد امنیت و حریم خصوصی هماهنگ شود.
۸. آیا Parse و TryParse از دید کارایی و حافظه از نظر Performance کند است؟
روی ورودی معتبر معمولاً تبدیل سریع است؛ مشکل اصلی زمانی رخ میدهد که داده نامعتبر زیاد باشد و Parse مرتب استثنا بسازد. اندازهگیری با داده واقعی، Release build، Runtime هدف و ابزار مناسب از حدس بهتر است.
۹. بهترین روش استفاده از Parse و TryParse از دید کارایی و حافظه چیست؟
فرهنگ و قالب را صریح کنید، تبدیل را در مرز ورودی نگه دارید، دامنه مجاز را جداگانه بسنجید، از تبدیل تکراری جلوگیری کنید و برای تمام کرانها تست داشته باشید. شکست قابل انتظار را نیز با TryParse مدل کنید.
۱۰. Parse و TryParse از دید کارایی و حافظه با کدام نسخههای C# و .NET سازگار است؟
شکلهای پایه Parse سالهاست در .NET وجود دارند، اما overloadهای Generic، Span و رابطهای جدید مانند IParsable به نسخه Runtime وابستهاند. پیش از استفاده از overload جدید، Target Framework پروژه و مستندات همان نسخه را کنترل کنید.