نوروز مبارک!
دریافت قسمت اضافه شده
لیست کامل این دوره در PluralSight
- Explicit
- Implicit
کامپایلر JIT
همانطور که در تصویر فوق مشاهده میکنید، سورس کد توسط کامپایلر دات نت به exe و یا dll کامپایل میشود. کامپایلر JIT تنها متدهایی را که در زمان اجرا(runtime) فراخوانی میشوند را کامپایل میکند. در دات نت فریم ورک سه نوع JIT Compilation داریم:
Normal JIT Compilation
در این نوع کامپایل، متدها در زمان فراخوانی در زمان اجرا کامپایل میشوند. بعد از اجرا، متد داخل حافظه ذخیره میشود. به متدهای ذخیره شده در حافظه jitted گفته میشود. دیگر نیازی به کامپایل متد jit شده نیست. در فراخوانی بعدی، متد مستقیماً از حافظه کش در دسترس خواهد بود.
Econo JIT Compilation
این نوع کامپایل شبیه به حالت Normal JIT است با این تفاوت که متدها بلافاصله بعد از اجرا از حافظه حذف میشوند.
Pre-JIT Compilation
یکی دیگر از حالتهای کامپایل برنامههای دات نتی Pre-JIT Compilation می باشد. در این حالت به جای متدهای مورد استفاده، کل اسمبلی کامپایل میشود. در دات نت میتوان اینکار را توسط Ngen.exe یا (Native Image Generator) انجام داد. تمام دستورالعملهای CIL قبل از اجرا به کد محلی(Native Code) کامپایل میشوند. در این حالت runtime میتواند از native images به جای کامپایلر JIT استفاده کند. این نوع کامپایل عملیات تولید کد را در زمان اجرای برنامه به زمان Installation منتقل میکند، در اینصورت برنامه نیاز به یک Installer برای اینکار دارد.
Multicore JIT
در دات نت فریم ورک 4.5 یک راه حل جایگزین دیگر برای بهینه سازی و بهبود سرعت اجرای برنامههای دات نت وجود دارد. همانطور که عنوان شد Ngen.exe برای در دسترس بودن نیاز به Installer برای برنامه دارد. توسط Multicore JIT متدها بر روی دو هسته به صورت موازی کامپایل میشوند، در اینصورت میتوانید تا 50 درصد از JIT Time صرفه جویی کنید.
Multicore JIT همچنین میتواند باعث بهبود سرعت در برنامههای WPF شود. در نمودار زیر میتوانید حالتهای استفاده و عدم استفاده از Multicore JIT را در سه برنامه WPF نوشته شده مشاهده کنید.
Multicore JIT در عمل
Multicore JIT از دو مد عملیاتی استفاده میکند: مد ثبت(Recording mode)، مد بازپخش(Playback mode)
در حالت ثبت کامپایلر JIT هر متدی که نیاز به کامپایل داشته باشد را رکورد میکند. بعد از اینکه CLR تعیین کند که اجرای برنامه به اتمام رسیده است، تمام متدهایی که اجرا شده اند را به صورت یک پروفایل بر روی دیسک ذخیره میکند.
هنگامیکه Multicore JIT فعال میشود، با اولین اجرای برنامه، حالت ثبت مورد استفاده قرار میگیرد. در اجراهای بعدی، از حالت بازپخش استفاده میشود. حالت بازپخش پروفایل را از طریق دیسک بارگیری کرده، و قبل از اینکه این اطلاعات توسط ترد اصلی مورد استفاده قرار گیرد، از آنها برای تفسیر (کامپایل) متدها در پیشزمینه استفاده میکند.
در نتیجه، ترد اصلی به کامپایل دیگری نیاز ندارد، در این حالت سرعت اجرای برنامه بیشتر میشود. حالتهای ثبت و بازپخش تنها برای کامپیوترهایی با چندین هسته فعال میباشند.
استفاده از Multicore JIT
در برنامههای 4.5 ASP.NET و 5 Silverlight به صورت پیش فرض این ویژگی فعال میباشد. ازآنجائیکه این برنامهها hosted application هستند؛ در نتیجه فضای مناسبی برای ذخیره سازی پروفایل در این نوع برنامهها موجود میباشد. اما برای برنامههای Desktop این ویژگی باید فعال شود. برای اینکار کافی است دو خط زیر را به نقطه شروع برنامه تان اضافه کنید:
public App() { ProfileOptimization.SetProfileRoot(@"C:\MyAppFolder"); ProfileOptimization.StartProfile("Startup.Profile"); }
توسط متد SetProfileRoot میتوانیم مسیر ذخیره سازی پروفایل JIT را مشخص کنیم. در خط بعدی نیز توسط متد StartProfile نام پروفایل را برای فعال سازی Multicore JIT تعیین میکنیم. در این حالت در اولین اجرای برنامه پروفایلی وجود ندارد، Multicore JIT در حالت ثبت عمل میکند و پروفایل را در مسیر تعیین شده ایجاد میکند. در دومین بار اجرای برنامه CRL پروفایل را از اجرای قبلی برنامه بارگذاری میکند؛ در این حالت Multicore JIT به صورت بازپخش عمل میکند.
همانطور که عنوان شد در برنامههای ASP.NET 4.5 و Silverlight 5 قابلیت Multicore JIT به صورت پیش فرض فعال میباشد. برای غیر فعال سازی آن میتوانید با تغییر فلگ profileGuidedOptimizations به None اینکار را انجام دهید:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <!-- ... --> <system.web> <compilation profileGuidedOptimizations="None" /> <!-- ... --> </system.web> </configuration>
مقدمه ای بر Free Style
With the release of Free Style 1.0, I figure it's about time to write about Free Style - how it works, why you'd want to use it and little introduction to CSS-in-JS. This has been a long time coming, with my first commit to Free Style over a year ago, and the first commit to Free Style in its current form 10 months ago. This is not a blog post designed to sway decisions - as always, you should use your own fair judgement.
بررسی تغییرات Blazor در دات نت 8
What's New in Blazor for .NET 8
Come find out about the future of Blazor in .NET 8! We'll explore all the upcoming features and improvements, including our effort to create a unified full stack web UI programming model that combines the strengths of client and server. We hope to see you there!
You will learn:
How Blazor is becoming the best option for full stack web development
How Blazor in .NET 8 will provide full flexibility to build web apps however works best for you
How to try out the latest Blazor features in .NET 8
let name: string; name = "Vahid"; // OK name = null; // OK name = undefined; // OK
let age: number; age = 24; // OK age = null; // OK age = undefined; // OK
نوع null در TypeScript
همانند JavaScript، نوع null تنها یک مقدار معتبر نال را میتواند داشته باشد و نمیتوان برای مثال یک رشته را به آن انتساب داد. اما انتساب این مقدار به هر نوع متغیر دیگری، سبب پاک شدن مقدار آن خواهد شد. با فعالسازی strictNullChecks، این نوع را تنها به نوعهای نالپذیر میتوان انتساب داد.
نوع undefined در TypeScript
هر متغیری که مقداری به آن انتساب داده نشده باشد، با undefined مقدار دهی میشود. این مورد حتی جهت خروجی متدها نیز صادق است و اگر return ایی در آنها فراموش شود، این خروجی نیز به undefined تفسیر میشود.
در اینجا نیز اگر نوع متغیری به undefined تنظیم شد، این متغیر تنها مقدار undefined را میتواند بپذیرد. تنها با خاموش کردن پرچم strictNullChecks میتوان آنرا به اعداد، رشتهها و غیره نیز انتساب داد.
فعالسازی نوعهای نال نپذیر در TypeScript
برای فعالسازی این قابلیت، نیاز است پرچم strictNullChecks را در فایل تنظیمات کامپایلر به true تنظیم کرد:
{ "compilerOptions": { "strictNullChecks": true } }
برای مثال اگر متدی، رشتهای را به عنوان پارامتر قبول کند، تا پیش از TypeScript 2.0 و فعالسازی strictNullChecks آن، مشخص نبود که رشتهی دریافتی از آن واقعا یک رشتهاست و یا شاید null. اما اکنون یک رشته، فقط یک رشتهاست و دیگر نال پذیر نیست.
let foo: string = null; // Error! Type 'null' is not assignable to type 'string'.
Uncaught ReferenceError: foo is not defined Uncaught TypeError: window.foo is not a function
این مورد برای آرایهها نیز صادق است:
// With strictNullChecks set to false let d: Array<number> = [null, undefined, 10, 15]; //OK let e: Array<string> = ["pie", null, ""]; //OK // With strictNullChecks set to true let d: Array<number> = [null, undefined, 10, 15]; // Error let e: Array<string> = ["pie", null, ""]; // Error
ساده سازی تعریف بررسیهای با پرچم strict، در TypeScript 2.3
تعداد گزینههای قابل تنظیم در فایل tsconfig روز به روز بیشتر میشوند. به همین جهت برای ساده سازی فعالسازی آنها، از TypeScript 2.3 به بعد، پرچم strict نیز به این تنظیمات اضافه شدهاست. کار آن فعالسازی یکجای تمام بررسیهای strict است؛ مانند noImplicitAny، strictNullChecks و غیره.
{ "compilerOptions": { "strict": true /* Enable all strict type-checking options. */ } }
{ "compilerOptions": { "strict": true, "noImplicitThis": false } }
یک نکته: اجرای دستور tsc --init ، سبب تولید یک فایل tsconfig.json از پیش تنظیم شده، بر اساس آخرین قابلیتهای کامپایلر TypeScript میشود.
اما ... اکنون چگونه یک نوع را نالپذیر کنیم؟
TypeScript به همراه دو نوع ویژهی null و undefined نیز شدهاست که تنها دارای مقادیر null و undefined میتوانند باشند. به این معنا که در حین تعریف نوع یک متغیر، میتوان این دو را نیز ذکر کرد و دیگر تنها به عنوان دو مقدار مطرح نیستند. به این ترتیب میتوان از آنها یک union type را ایجاد کرد:
let foo: string | null = null; // Okay!
let name: string | null; name = "Vahid"; // OK name = null; // OK name = undefined; // Error
یک نکته:
تا پیش از این اگر متغیری را به این صورت تعریف میکردیم:
let z = null;
بررسی انتساب، پیش از استفاده
با فعالسازی strictNullChecks، اکنون کامپایلر برای تمام نوعهایی که undefined نیستند، یک مقدار اولیه را پیش از استفادهی از آنها درخواست میکند:
testAssignedBeforeUseChecking() { let x: number; console.log(x); }
[ts] Variable 'x' is used before being assigned.
اما در حالت ذیل، عدد z میتواند عدد و یا undefined باشد؛ به همین جهت کامپایلر با استفادهی از آن مشکلی نخواهد داشت:
let z: number | undefined; console.log(z);
یک نکته: خواص و پارامترهای اختیاری، به صورت خودکار دارای نوع undefined نیز هستند. برای مثال امضای متد ذیل:
method1(x?: number) { }
method1(x?: number | undefined) { }
اجبار به بررسی نال نبودن مقادیر، پیش از استفادهی از آنها در متدهای نال نپذیر
اگر پارامتر متدی یا خاصیت شیءایی نال پذیر نباشند، با ارسال مقدار نوعی به آنها که میتواند null و یا undefined را بپذیرد، یک خطای زمان کامپایل صادر خواهد شد. در اینجا محافظهای نوعها توسعه یافتهاند تا اگر بررسی نال یا undefined بودن مقداری انجام شد، مشکلی در جهت استفادهی از آنها نباشد:
f(x: number): string { return x.toString(); } testTypeGuards() { let x: number | null | undefined; if (x) { this.f(x); // Ok, type of x is number here } else { this.f(x); // Error, type of x is number? here } }
Argument of type 'number | null | undefined' is not assignable to parameter of type 'number'. Type 'undefined' is not assignable to type 'number'.
امکان این بررسی در مورد عبارات شرطی نیز صادق است:
getLength(s: string | null) { return s ? s.length : 0; }
توسعهی محافظهای نوعها جهت کار با نوعهای نال نپذیر
در مثال ذیل، خروجی متد isNumber دارای امضایی به همراه is است:
isNumber(n: any): n is number { // type guard return typeof n === "number"; }
usedMb(usedBytes?: number): number | undefined { return this.isNumber(usedBytes) ? (usedBytes / (1024 * 1024)) : undefined; }
usedMb2(usedBytes?: number): number | undefined { return usedBytes ? (usedBytes / (1024 * 1024)) : undefined; }
همچنین امضای متد نیز به number | undefined تغییر یافتهاست. در غیر اینصورت، خطای زمان کامپایل Type undefined is not assignable to type number صادر خواهد شد.
در حین استفادهی از یک چنین متدی، دیگر نمیتوان به خروجی آن به صورت ذیل دسترسی یافت:
formatUsedMb(): string { //ERROR: TS2531: Object is possibly undefined return this.usedMb(123).toFixed(0).toString(); }
formatUsed(): string { const usedMb = this.usedMb(123); return usedMb ? usedMb.toFixed(0).toString() : ""; }
لغو بررسی strictNullChecks به صورت موقت
با استفاده از اپراتور ! میتوان به کامپایلر اطمینان داد که این متغیر یا خاصیت، دارای مقدار نال نیست و نخواهد بود:
export interface User { name: string; age?: number; }
printUserInfo(user: User) { if (user.age != null) { console.log(`${user.name}, ${user.age.toString()}`); } }
printUserInfo(user: User) { console.log(`${user.name}, ${user.age.toString()}`); }
و یا میتوان توسط اپراتور ! این بررسی را به صورت موقت خاموش کرد:
printUserInfo(user: User) { console.log(`${user.name}, ${user.age!.toString()}`); }
[tslint] Forbidden non null assertion (no-non-null-assertion)
یک نکتهی تکمیلی
پس از آزمایش موفقیت آمیز نوعهای نال نپذیر در TypeScript، مایکروسافت قصد دارد این ویژگی را به C# 8.0 نیز در مورد نوعهای ارجاعی که میتوانند نال پذیر باشند، اضافه کند (امکان داشتن نوعهای ارجاعی نالنپذیر).
زبان برنامه نویسی Erlang
زبان Erlang در سال 1986 توسط شرکت Ericson سوئد به منظور استفاده در سرورهای switching تلفن ساخته شد. این زبان توسط تیمی به سرپرستی Joe Armstrong معرفی شد تا بتواند از برنامههای توزیعشده، مقاوم در برابر خطا، بلادرنگ و بیوقفه پشتیبانی کند. بعدها این زبان به شکل متنباز در اختیار عموم قرار گرفت. یکی از روشهای برنامه نویسی که توسط این برنامه میشه ازش استفاده کرد، روش تابعی (Functional Programming) هست. این روش قبلا وجود داشت و مدتی هم از مد افتاد، ولی با اومدن پردازندههای چند هسته ای استفاده از زبانهای برنامه نویسی که میشه با اونها تابعی نوشت از سر گرفته شد و حتی مایکروسافت در سال 2010 زبان برنامه نویسی #F رو معرفی کرد. یکی از قابلیتهای زبانهای تابعی سرعت اجرا شدن کدهای اونها هست که اونها رو از زبانهای امری مثل #C و Java جدا میکنه.
Scala هم یک زبان برنامه نویسی همه منظوره هست که ویژگی هایی رو از زبانهای برنامه نویسی شیء گرا داره و همچنین توسط اون میشه برنامه نویسی تابعی انجام داد. از اون به عنوان جانشینی برای جاوا یاد میکنند چون قابلتهای اضافه بر جاوا رو داره.
Intermediate & Advanced
استفاده از XQuery - قسمت اول
XQuery پیاده سازی شده در SQL Server با استانداردهای XQuery 1.0 و XPath 2.0 سازگار است. XQuery برای کار با نودهای مختلف یک سند XML، از XPath استفاده میکند. همچنین باید دقت داشت که این زبان به بزرگی و کوچکی حروف حساس است. در آن تمام واژههای کلیدی lowercase هستند و تمام متغیرها با علامت $ شروع میشوند.
ورودی و خروجی در XQuery
استاندارد XQuery از یک سری توابع ورودی مانند doc برای کار با یک سند و collection برای پردازش چندین سند کمک میگیرد. SQL Server از هیچکدام از این توابع پشتیبانی نمیکند. در اینجا از XQuery، به کمک متدهای نوع دادهای XML استفاده خواهد شد. این متدها شامل موارد ذیل هستند:
- query : یک xml را به عنوان ورودی گرفته و نهایتا یک خروجی XML دیگر را بر میگرداند.
- exist : خروجی bit دارد؛ true یا false.
- value : یک خروجی SQL Type را ارائه میدهد.
- nodes : خروجی جدولی دارد.
- modify : برای تغییر اطلاعات بکار میرود.
این موارد را در طی مثالهایی بررسی خواهیم کرد. بنابراین در ادامه نیاز است یک سند XML را که در طی مثالهای این قسمت مورد استفاده قرار خواهد گرفت، به شرح ذیل مدنظر داشته باشیم:
DECLARE @data XML SET @data = '<people> <person> <name> <givenName>name1</givenName> <familyName>lname1</familyName> </name> <age>33</age> <height>short</height> </person> <person> <name> <givenName>name2</givenName> <familyName>lname2</familyName> </name> <age>40</age> <height>short</height> </person> <person> <name> <givenName>name3</givenName> <familyName>lname3</familyName> </name> <age>30</age> <height>medium</height> </person> </people>'
همانطور که در قسمت قبل نیز ذکر شد، اگر اطلاعات شما در یک فایل XML قرار دارند، نحوهی خواندن آن به شکل یک فیلد XML با کمک openrowset مطابق دستورات زیر خواهد بود:
declare @data xml set @data = (select * from openrowset(bulk 'c:\path\data.xml', single_blob) as x)
بررسی متد query
متد query یک XQuery متنی را دریافت کرده، آنرا بر روی XML ورودی اجرا نموده و سپس یک خروجی XML دیگر را ارائه خواهد داد.
اگر به کتابهای استاندارد XQuery مراجعه کنید، به یک چنین کوئریهایی خواهید رسید:
for $p in doc("data.xml")/people/person where $p/age > 30 return $p/name/givenName/text()
SELECT @data.query(' for $p in /people/person where $p/age > 30 return $p/name/givenName/text() ')
بررسی متد value
در ادامه متد value را بررسی خواهیم کرد. در اینجا قصد داریم مقدار سن اولین شخص را نمایش دهیم:
SELECT @data.value('/people/person/age', 'int')
اگر کوئری فوق را اجرا کنیم با خطای ذیل مواجه خواهیم شد:
XQuery [value()]: 'value()' requires a singleton (or empty sequence), found operand of type 'xdt:untypedAtomic *'
برای رفع این مشکل و اشاره به اولین شخص، میتوان از روش ذیل استفاده کرد:
SELECT @data.value('(/people/person/age)[1]', 'int')
تولید schema برای سند XML بحث جاری
با استفاده از برنامه Infer.exe مایکروسافت به سادگی میتوان برای یک سند XML، فایل Schema ایجاد کرد. این برنامه را از اینجا میتوانید دریافت کنید. پس از آن، اگر فرض کنیم اطلاعات سند XML مثال فوق در فایلی به نام people.xml ذخیره شدهاست، میتوان schema آنرا توسط دستور ذیل تولید کرد:
Infer.exe people.xml -o schema.xsd
که نهایتا چنین شکلی را خواهد داشت:
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="people"> <xs:complexType> <xs:sequence> <xs:element maxOccurs="unbounded" name="person"> <xs:complexType> <xs:sequence> <xs:element name="name"> <xs:complexType> <xs:sequence> <xs:element name="givenName" type="xs:string" /> <xs:element name="familyName" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="age" type="xs:unsignedByte" /> <xs:element name="height" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
این خروجی را که اکنون به صورت یک فایل xsd، در کنار فایل xml معرفی شده به آن میتوان یافت، با استفاده از openrowset قابل بارگذاری است:
declare @schema xml set @schema = (select * from openrowset(bulk 'c:\path\schema_1.xsd', single_blob) as x)
سپس از این متغیر برای تعریف یک اسکیما کالکشن جدید استفاده خواهیم کرد:
CREATE XML SCHEMA COLLECTION poeple_xsd AS @schema
DECLARE @data XML(poeple_xsd) SET @data = 'مانند قبل با همان محتوایی که در ابتدای بحث عنوان شد'
SELECT @data.value('/people/person[1]/age', 'int')
XQuery [value()]: 'value()' requires a singleton (or empty sequence), found operand of type 'xs:unsignedByte *'
مشکل کوئری نوشته در اینجا این است که زمانیکه نوع XML تعریف میشود، پیش فرض آن content است. یعنی در این حالت چندین root elemnt مجاز هستند. بنابراین person 1 درخواستی، میتواند چندین خروجی داشته باشد که در متد value مجاز نیست. این متد، پیش از اجرای کوئری، توسط parser تعیین اعتبار میشود و الزاما نیازی نیست تا حتما اجرا شده و سپس مشخص شود که چندین خروجی حاصل آن است.
اینبار تنها کاری که باید برای رفع مشکل گزارش شده انجام شود، تغییر content پیش فرض به document است:
DECLARE @data XML(document poeple_xsd)
sequences در XQuery
Sequences بسیار شبیه به آرایهای از آیتمها هستند و منظور مجموعهای از نودها یا مقادیر آنها است. برای مثال به ورودی کوئریهای XQuery به شکل توالی از یک سند و به خروجی آنها همانند توالی صفر تا چند نود نگاه کنید.
DECLARE @x XML SET @x='' SELECT @x.query( ' 1,2 (: 1,2 :) ')
همچنین باید دقت داشت که این توالی خطی تفسیر میشود.
DECLARE @x XML SET @x='' SELECT @x.query( ' for $x in (1,2,3) for $y in (4,5) return ($x,$y) ')
به علاوه در SQL Server امکان تعریف Heterogeneous sequences وجود ندارد؛ به عبارتی توالی بین مقادیر و نودها مجاز نیست. برای مثال اگر کوئری زیر را اجرا کنید:
DECLARE @x XML SET @x='' SELECT @x.query( ' 1, <node/> ')
XQuery [query()]: Heterogeneous sequences are not allowed: found 'xs:integer' and 'element(node,xdt:untyped)'
معرفی C#/WinRT Version 1.0
Today is the official GA release for .NET 5, and along with it we are excited to share the latest updates with our recent release of C#/WinRT version 1.0. C#/WinRT provides WinRT projection support for .NET 5 based apps. The Windows SDK leverages this technology and is now integrated with the .NET 5.0 SDK to expose Windows APIs through the new Target Framework Monikers. In addition to the Windows SDK support added for .NET 5, C#/WinRT itself allows component authors to build their own .NET 5 projections using the CsWinRT NuGet package.