تغییر در رفتار متد Reverse بر روی آرایهها در C# 14
نویسنده: وحید نصیری
تاریخ: ۱۴۰۴/۰۸/۰۱ ۱۰:۳۱
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
Reverse بر روی آرایهها است. این تغییر، که ناشی از بهبودهای مربوط به spanها است، میتواند باعث شود که کدهای قدیمی به طور غیرمنتظرهای رفتار کنند. در این مقاله، این تغییر را به طور کامل بررسی میکنیم، دلایل آن را توضیح میدهیم، تأثیرات آن را بحث میکنیم و راهحلهایی برای رفع مشکل ارائه میدهیم. x.Reverse() را بر روی یک آرایه (مثل int[] x) فراخوانی میکردید، کامپایلر متد Enumerable.Reverse(this IEnumerable از فضای نام System.Linq را انتخاب میکرد. این متد رفتار زیر را داشت:x) بدون تغییر باقی میماند (هیچ جهشی/تغییری یا mutation رخ نمیدهد).IEnumerable است که میتوانید آن را به متغیر دیگری اختصاص دهید یا در حلقهها استفاده کنید.int[] x = new[] { 1, 2, 3 };
var y = x.Reverse(); // y حالا {3, 2, 1} است، اما x همچنان {1, 2, 3} باقی میماند.
foreach (var item in y)
{
Console.WriteLine(item); // خروجی: 3, 2, 1
}System.Memory) باشد، کامپایلر رفتار متفاوتی نشان میدهد. حالا، متد x.Reverse() به جای انتخاب Enumerable.Reverse, متد MemoryExtensions.Reverse(this Span از فضای نام System.Memory را ترجیح میدهد. این تغییر به دلایل زیر رخ میدهد:Span یا ReadOnlySpan در سناریوهای بیشتری قابل اعمال باشند. در نتیجه، کامپایلر Span را به عنوان یک گزینه خاصتر (more specific) نسبت به IEnumerable انتخاب میکند.MemoryExtensions.Reverse آرایه را درجا (in-place) معکوس میکند و هیچ مقداری برنمیگرداند (نوع بازگشتی void است). این یعنی:x) تغییر میکند (mutated میشود).var y = x.Reverse();)، y همیشه null خواهد بود، زیرا متد چیزی برنمیگرداند. این میتواند منجر به خطاهای کامپایل یا runtime شود.int[] x = new[] { 1, 2, 3 };
var y = x.Reverse(); // حالا کامپایلر MemoryExtensions.Reverse را انتخاب میکند. y null است و x به {3, 2, 1} تغییر کرده است.
foreach (var item in x)
{
Console.WriteLine(item); // خروجی: 3, 2, 1 (آرایه اصلی تغییر کرده!)
}Enumerable.Reverse(this T[]) اضافه شده است که اولویت بالاتری دارد و رفتار قدیمی را حفظ میکند.Reverse, بلکه برای دیگر متدهای مشابه (مانند برخی عملیات در MemoryExtensions) نیز ممکن است رخ دهد. برای مثال، در مواردی که آرایههای covariant (مانند object[] حاوی string[]) استفاده میشود، ممکن است خطاهای runtime مانند ArrayTypeMismatchException ایجاد شود.Reverse را به متغیری اختصاص دهید، کامپایلر ممکن است خطا دهد زیرا نوع بازگشتی void است.ReadOnlySpan میتواند منجر به exceptionهای runtime شود.x.Reverse()، از Enumerable.Reverse(x) استفاده کنید. این کار کامپایلر را مجبور به انتخاب overload درست میکند.var y = Enumerable.Reverse(x); // رفتار قدیمی حفظ میشود.
public static class ArrayExtensions
{
public static IEnumerable<T> Reverse<T>(this T[] source) => Enumerable.Reverse(source);
}Enumerable.Reverse(this T[]) به طور خودکار انتخاب میشود و مشکل حل میشود.ReadOnlySpan وجود دارند، ممکن است خطاهای runtime در آرایههای covariant ایجاد شود. مثلاً:object[] objects = new string[] { "a" };
// در C# 14 ممکن است به Span<object> تبدیل شود و exception بدهد.Enumerable.Reverse اضافه شدهاند. این بخشی از تلاش برای جلوگیری از شکستهای گسترده است.Reverse بر روی آرایهها در C# 14، نمونهای از چگونگی تأثیر بهبودهای عملکردی بر کدهای موجود است. با درک دلایل و اعمال راهحلهای ساده، میتوانید از مشکلات جلوگیری کنید. اگر پروژهای بزرگ دارید، پیشنهاد میشود کد را بازبینی کنید و به .NET 10 ارتقا دهید تا از مزایای کامل C# 14 بهره ببرید.