اشتراک‌ها
معرفی Script#؛ اسکریپت نویسی با جاوا‌اسکریپت در دات‌نت

#Script is a simple, fast, highly versatile and embeddable scripting language for .NET Core and .NET Apps that utilizes a familiar JavaScript inspired expressive Syntax to enable dynamic scripting of .NET Apps via controlled access to pluggable methods and arguments within a sandbox environment - ensuring scripts are encapsulated and encourages the use of reusable and testable components where live environments can be easily re-created and simulated.  

معرفی Script#؛ اسکریپت نویسی با جاوا‌اسکریپت در دات‌نت
اشتراک‌ها
net SmokeTest. ابزاری برای تست اسمبلی‌های دات‌نت
اگر یک اسمبلی دات‌نت بدون سورس کد داشته باشید و بخواهید توابعی از اون رو فراخوانی کنید، چه خواهید کرد؟
می‌توانید از net SmokeTest. برای این منظور بدون نوشتن حتی یک خط کد استفاده کنید.


نکته جالب اینکه این ابزار به شکل افزونه برای NET Reflector. نیز فراهم شده است.


net SmokeTest. ابزاری برای تست اسمبلی‌های دات‌نت
مطالب
بررسی بهبودهای پروسه‌ی Build در دات‌نت 8

در نگارش‌های اخیر دات‌نت، NET CLI. به همراه تغییرات قابل توجهی بوده‌است که در این مطلب و نظرات آن، موارد مهم این تغییرات را بررسی خواهیم کرد.

console logger بهبود یافته‌ی دات‌نت 8

یکی از تغییرات بسیار جالب توجه و مفید NET CLI. در دات‌نت 8، امکان دسترسی به خروجی لاگ‌های ساختار یافته‌ی اعمال خط فرمان آن است:

اگر پروژه‌ی خود را با استفاده از دستور dotnet build، کامپایل می‌کنید، خروجی پیش‌فرض این دستور خط فرمان، کلی و بدون ارائه‌ی جزئیات است؛ اما می‌توان آن‌را در دات‌نت 8، به شکل تصویر فوق، تغییر داد و به این مزایا رسید:

  • امکان مشاهده‌ی زمان کامپایل هر قسمت به صورت جداگانه
  • امکان مشاهده‌ی پویای درصد انجام عملیات
  • امکان مشاهده‌ی جزئیات کامپایل هر target framework به صورت مجزا
  • دسترسی به یک خروجی رنگی و زیباتر

این خروجی را که به صورت پیش‌فرض فعال نیست، می‌توان به دو صورت:

الف) سراسری و با اجرای دستور PowerShell زیر:

[Environment]::SetEnvironmentVariable("MSBUILDTERMINALLOGGER", "auto", "User")

که متغیر محیطی MSBUILDTERMINALLOGGER را به auto تنظیم می‌کند،

ب) و یا با استفاده از سوئیچ tl-- به ازای هر دستور dotnet build، به صورت جداگانه‌ای فعال کرد:

dotnet build --tl

یک نکته: این قابلیت جالب و مهم، در دات نت 9، به صورت پیش‌فرض فعال است و نیازی به تنظیم خاصی ندارد.

مطالب
intern pool جدول نگهداری رشته‌ها در دات‌نت
کد زیر را در نظر بگیرید :
object text1 = "test";
object text2 = "test";

object num1 = 1;
object num2 = 1;

Console.WriteLine("text1 == text2 : " + (text1 == text2));
Console.WriteLine("num1 == num2 : " + (num1 == num2));

به نظر شما چه چیزی در خروجی نمایش داده میشود؟

هر چهار متغییر text1  و text2 و num1 و num2 از نوع object هستند. با اینکه مقدار text1 و text2 یکی و مقدار num1 و num2 هم یکی است، نتیجه text1==text2 برابر true است اما num1==num2 برابر false.

خطی که text2 تعریف شده است را تغییر میدهیم :
object text2 = "test".ToLower();

اینبار با این که باز مقدار text1 و text2 یکی و هر دو "test" است، اما نتیجه text1==text2 برابر false است. انتظار ما هم همین است. دو object ایجاد شده است و یکی نیستند. تنها در صورتی باید نتیجه == آنها true باشد که هر دو به یک object اشاره کنند.

اما چرا در کد اولی اینگونه نبود؟

دلیل این کار برمیگردد به رفتار دات‌نت نسبت به رشتههایی که به صورت صریح در برنامه تعریف میشوند. CLR یک جدول برای ذخیره رشتهها به نام intern pool برای برنامه میسازد. هر رشتهای تعریف میشود، اگر در intern pool رشتهای با همان مقدار وجود نداشته باشد، یک رشته جدید ایجاد و به جدول اضافه میشود، و اگر موجود باشد متغییر جدید فقط به آن اشاره میکند. در واقع اگر 100 جای برنامه حتی در کلاسهای مختلف، رشتههایی با مقادیر یکسان وجود داشته باشند، برای همه آنها یک نمونه وجود دارد.

بنابراین text1 و text2 در کد اولی واقعا یکی هستند و یک نمونه برای آنها ایجاد شده است.

البته چند نکته در اینجا هست :
اگر text1 و text2 به صورت string تعریف شوند، نتیجه text1==text2 در هر دو حالت فوق برابر true است. چون عملگر == در کلاس string یکبار دیگر overload شده است:
public sealed class String : ...
{
    ...
    public static bool operator ==(string a, string b)
    {
      return string.Equals(a, b);
    }
   ...
}

این که کدام یک از overload‌ها اجرا شوند (کلاس پایه، کلاس اصلی، ...) به نوع دو متغییر اطراف == بستگی دارد. مثلا در کد زیر :
string text1 = "test";
string text2 = "test".ToLower();

Console.WriteLine("text1 == text2 (string) : " + (text1 == text2));
Console.WriteLine("text1 == text2 (object) : " + ((object)text1 == (object)text2));

اولین نتیجه true و دومی false است. چون در اولی عملگر == تعریف شده در کلاس string مورد استفاده قرار می‏‏گیرد اما در دومی عملگر == تعریف شده در کلاس object.

اگر دقت نشود این رفتار مشکلزا میشود. مثلا حالتی را در نظر بگیرید که text1 ورودی کاربر است و text2 از بانک اطلاعاتی خوانده شده است و با اینکه مقادیر یکسان دارند نتیجه == آنها false است. اگر تعریف عملگرها در کلاس object به صورت virtual بود و در کلاس‌های دیگر override می‌شد، این تغییر نوع‌ها تاثیری نداشت. اما عملگرها به صورت static تعریف می‌شوند و امکان override شدن ندارند. به همین خاطر کلاس object متدی به اسم Equals در اختیار گذاشته که کلاس‌ها آنرا override می‌کنند و معمولا از این متد برای سنجش برابری دو کلاس استفاده می‌شود :
object text1 = "test";
object text2 = "test".ToLower();

Console.WriteLine("text1 Equals text2 : " + text1.Equals(text2));
Console.WriteLine("text1 Equals text2 : " + object.Equals(text1, text2));

البته یادآور می‌شوم که فقط رشته‌هایی که به صورت صریح در برنامه تعریف شده‌اند، در intern pool قرار می‌گیرند و این فهرست شامل رشته‌هایی که از فایل یا بانک اطلاعاتی خوانده می‌شوند یا در برنامه تولید می‌شوند، نیست. این کار منطقی است وگرنه حافظه زیادی مصرف خواهد شد.

با استفاده از متد string.Intern می‌توان یک رشته را که در intern pool وجود ندارد، به فهرست آن افزود. اگر رشته در intern pool وجود داشته باشد، reference آنرا بر می‌گرداند در غیر اینصورت یک reference به رشته جدید به intern pool اضافه می‌کند و آنرا برمی‌گرداند.

یک مورد استفاده آن هنگام lock روی رشته‌هاست. برای مثال در کد زیر DeviceId یک رشته است که از بانک اطلاعاتی خوانده می‌شود و باعث می‌شود که چند job همزمان به یک دستگاه وصل نشوند :
lock (job.DeviceId)
{
    job.Execute();
}

اگر یک job با DeviceId برابر COM1 در حال اجرا باشد، این lock جلوی اجرای همزمان job دیگری با همین DeviceId را نمی‌گیرد. زیرا هر چند مقدار DeviceId دو job یکی است ولی به یک نمونه اشاره نمی‌کنند.

می‌توان lock را اینگونه اصلاح کرد :
lock (string.Intern(job.DeviceId))
{
    job.Execute();
}

اشتراک‌ها
بررسی بهبودهای کارآیی LINQ در دات‌نت 9
.NET 9 LINQ Performance Improvements

Benchmark comparisons between .NET 8 and .NET 9 show that certain LINQ queries execute up to 30% faster, depending on the dataset and query complexity. These improvements are particularly impactful for performance-critical applications, where even small gains can add up to substantial boosts.
بررسی بهبودهای کارآیی LINQ در دات‌نت 9
مطالب
نصب Mono Develop 4.x در Ubuntu
پیشنیازها

در قسمت قبل، موفق به نصب Mono 3.0 در لینوکس شدیم. در ادامه قصد داریم یک IDE لینوکسی مخصوص کار با Mono را به نام Mono Develop بر روی Ubuntu نصب کنیم. اگر مونو را نصب کرده‌اید، نیاز است پیشنیازهای ذیل را بر روی سیستم خود نصب کنید:
 sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install -y build-essential libc6-dev g++ gcc libglib2.0-dev pkg-config \
 git-core apache2 apache2-threaded-dev bison gettext autoconf automake libtool \
libpango1.0-dev libatk1.0-dev libgtk2.0-dev libtiff5-dev libgif-dev libglade2-dev curl \
python-software-properties gawk libjpeg-dev libexif-dev flex checkinstall intltool git \
libcairo2-dev libgnomecanvas2-dev libgnome2-dev libgnomeui-dev libgnomeprint2.2-dev \
libgnomeprintui2.2-dev libgtkhtml3.14-dev libgtksourceview2.0-dev librsvg2-dev libvte-dev \
libnspr4-dev libnss3-dev libwebkit-dev apache2-threaded-dev libpng12-dev libfontconfig1-dev \
libfreetype6-dev zlib1g-dev libjpeg8-dev libjpeg-turbo8-dev libart-2.0-dev libgnomevfs2-dev \
libgnome-desktop-dev libnautilus-extension-dev libwnck-dev libvala-0.18-dev \
mono-addins-utils gtk-sharp2 gnome-sharp2
نصب این پیشنیارها ضروری بوده و در غیر اینصورت موفق به build کامل Mono Develop نخواهید شد. برای مثال پیغام خطای ذیل را در انتهای build دریافت می‌کنید؛ به این معنا که اسمبلی‌های ذیل کامپایل نشده‌اند:
 * art-sharp.dll: no
* gnomevfs-sharp.dll: no
* gnome-sharp.dll: no
و یا عنوان می‌کند که  gnome-sharp.dll برای کامپایل نیاز به یک سری کتابخانه کمکی دیگر نیز دارد:
  gnome-sharp.dll requires libgnomecanvas, libgnome, and libgnomeui.


نصب متداول محیط برنامه نویسی Mono Develop

برای نصب یک IDE که بتوان تحت همان لینوکس نیز کار برنامه نویسی دات نت را انجام داد، می‌توان از Mono deveop استفاده کرد. برای نصب آن فرمان ذیل را در خط فرمان لینوکس صادر نکنید !
 sudo apt-get install monodevelop
این روش هر چند کار می‌کند، اما تا این تاریخ، نگارش 3 را نصب خواهد کرد؛ با توجه به اینکه آخرین نگارش موجود در سایت Mono Develop، نگارش 4 است. همچنین نصب آن نیز نگارش جاری Mono را به نگارش 2 آن تنظیم می‌کند که جالب نیست. اگر به اشتباه آن‌را نصب کرده‌اید، برای حذف مونو از دستور ذیل استفاده کنید:
 sudo apt-get purge cli-common mono-runtime
همچنین الان کلیه مسیرهای سیستم به هم ریخته است. برای رفع آن مسیر نصب Mono-3.0 را باید به نحو ذیل مجددا تنظیم کرد:
 export PATH=/opt/mono-3.0/bin:$PATH
export PKG_CONFIG_PATH=/opt/mono-3.0/lib/pkgconfig:$PKG_CONFIG_PATH


نصب محیط برنامه نویسی Mono Develop از روی مخزن کد آن

دریافت و نصب وابستگی‌های Monodevelop جهت کامپایل سورس آن، شاید نصف روز شما را به خود اختصاص دهد؛ به علاوه حداقل مصرف حدود 500 مگابایت حجم اینترنت. راه ساده‌تری نیز برای دریافت آخرین نگارش سازگار با Ubuntu آن وجود دارد و آن هم استفاده از بسته‌های شخصی کامپایل شده است؛ که اصطلاحا به آن‌ها PPA نیز گفته می‌شود. برای مثال: (^ و ^ )
چند نمونه بسته شخصی برای دریافت ساده آخرین نگارش Mono develop جهت نصب بر روی Ubuntu : (^ و ^ و ^ )
و به صورت خلاصه فرامین ذیل را در ترمینال لینوکس اجرا کنید تا از بسته شخصی keks9n استفاده کنیم:
 sudo add-apt-repository ppa:keks9n/monodevelop-latest
sudo apt-get update
sudo apt-get install monodevelop-latest
این روش، از تمام روش‌های ذکر شده تا کنون، ساده‌تر است. از این لحاظ که mono 3.2.1 را نیز به صورت خودکار بر روی سیستم شما نصب می‌کند (این بسته شخصی، به صورت خودکار هر از چندگاهی آخرین نگارش مونو، وابستگی‌های آن و monodevelop جدید را بسته بندی و ارائه می‌دهد).
بنابراین اگر مونو 3.2.1 یا جدیدتر را هنوز نصب نکرده‌اید، همین سه سطر فوق، کار نصب کلی آن‌را نیز انجام می‌دهد؛ علاوه بر نصب monodevelop در آخر کار به همراه تمام پیشنیازهای لازم مانند gtk-sharp و gnome-sharp.
پس از نصب کامل، برای اجرای آن در همان خط فرمان، دستور monodevelop را صادر کنید.