PDA

توجه ! این یک نسخه آرشیو شده می باشد و در این حالت شما عکسی را مشاهده نمی کنید برای مشاهده کامل متن و عکسها بر روی لینک مقابل کلیک کنید : بررسی نسخه دات نت فريم ورك 4.0، ساختارهاي جديد bcl



Borna66
08-28-2012, 11:32 PM
مقدمه
توسعه دات نت فريم ورك مايكروسافت اواخر دهه 1990 با نام (Next Generation Windows Services (NGWS آغاز شد. اواخر سال 2000 بود كه نخستين نسخه بتاي دات نت فريم ورك 1.0 منتشر شد. تاكنون شش نسخه دات نت فريم ورك ارائه شده است كه آخرين نسخه، امسال با ورژن 4.0 همراه با ويژوال استوديو 2010 در اختيار توسعه دهندگان و برنامه نويسان سراسر جهان قرار گرفت. در جدول زير تمامي ورژن هاي دات نت فريم ورك از ابتدا تاكنون با جزئيات كامل نمايش داده شده اند.


http://pnu-club.com/imported/2012/08/108.png


تصوير زير نيز نمايي كلي از ساختار دات نت فريم ورك 4.0 ارائه مي دهد.


http://pnu-club.com/imported/2012/08/109.png


يكي از ساختارهاي بنيادي و اوليه دات نت فريم ورك از ابتدا تاكنون Base Class Library يا به اختصار BCL بوده است. اين كتابخانه كلاس ها و انواع پايه اي را در خود جاي داده است كه توابع ابتدايي را بين تمامي زبان هاي دات نت به اشتراك مي گذارند. از جمله اين عمليات مي توان خواندن و نوشتن اطلاعات فايل ها، دسترسي به پايگاه داده ها، پردازش هاي گرافيكي و دسترسي به فايل هاي XML را نام برد. BCL فضاهاي نام زير را شامل مي شود:



System

System.CodeDom

System.Collections

System.Diagnostics

System.Globalization

System.IO

System.Resources

System.Text

System.Text.RegularExpressions



عمده مباحث ارائه شده در BCL 4.0 به شرح زير مي باشند:



Support for code contracts
Parallel extensions
Support for tuples
File IO improvements
Support for memory mapped files
A sorted set collection
A lazy type
Support for arbitrarily large integers
Globalization data updates
Improved System.Resourcesresource lookup fallback logic
Compression improvements



در اين مقاله و مقاله بعدي سعي خواهيم كرد تا مهم ترين مباحث BCL 4.0 را مورد بحث و بررسي قرار دهيم.

نوع جديد Tuple
نوع Tuple در بسياري از زبان هاي تابعي و پويا مانند #F و Iron Python، به صورت پيش تعريف شده وجود دارد. همانطور كه آرايه، به عنوان يك ساختمان داده مجموعه اي از المان ها را در كنار هم نگهداري مي كند، نوع Tuple نيز براي دسته بندي مجموعه اي ناهمگان از المان ها به كار مي رود. براي واضح شدن اين مطلب به تعريف نوع Tuple در فضاي نام System دقت كنيد:




public class Tuple<T1>







كه قابليت افزايش تا هشت المان را دارد:



public class Tuple<T1, T2, T3, T4, T5, T6, T7, TRest>






نحوه تعريف Tuple در مثال ساده زير نمايش داده شده است:



static void Main(string[] args)
{
var PdTuple = Tuple.Create<string, int>("Article", 13);
Console.WriteLine(PdTuple);
Console.Read();
}








در اين مثال يك Tuple از نوع دوتايي string - int تعريف شده است و خروجي به صورت زير مي باشد :



<Article,13>




با توجه به مطالب و مثال بيان شده نكات زير در رابطه با نوع Tuple قابل برداشت مي باشند:



طول Tuple پس از تعريف، قابل تغيير نمي باشد.
Tuple مي تواند مقادير غيرهم نوع را نگهداري كند (ناهمگن) ولي پس از تعريف نمي توان نوع آيتم هاي آن را تغيير داد. به عبارتي Type Saftyدر خصوص Tuple رعايت مي شود.
حداكثر تعداد هشت المان مي توانند در يك Tuple نگهداري شوند كه آخرين المان خود بايد از نوع Tuple باشد.


Tuple از چه مزايايي برخوردار مي باشد؟
3.0 #C مفهوم جديدي به نام انواع بي نام (Anonymous Types) را معرفي كرد. با استفاده از نوع بي نام مي توان مقاديري را بدون تعريف كلاس و يا ساختار (struct) در برنامه ايجاد كرد. براي يادآوري به كد زير دقت كنيد:


var anonymousWebsite = new {Name = "PersiaDevelopers"};



عنوان آرگومان تابع و هم به عنوان مقدار بازگشتي بهره برد. براي روشن تر شدن مطلب، فرض كنيد كه كلاسي به نام Student حاوي تمامي اطلاعات دانشجو، تعريف شده است. اما در مواردي تنها نيازمند نام دانشجو و شماره دانشجويي هستيم. مي توان تابعي تعريف كرد كه ليستي از اين دو خصيصه در قالب يك Tuple به شكل زير برگرداند:
anonymousWebsite نوع بي نامي بوده كه يك خصيصه Name دارد. محدوديت بزرگ انواع بي نام اين است كه تنها در حوزه هاي محلي داخل توابع قابل تعريف و استفاده بوده و نمي توان به عنوان آرگومان توابع و يا مقدار بازگشتي از آنها استفاده كرد. در سناريوهايي كه با محدوديت هاي انواع بي نام مواجه هستند، مي توان از نوع Tuple هم به



public static List<Tuple<string,int>> GetAbstractStudentsInfo()
{
List<Tuple<string,int>> abstractInfo = new List<Tuple<string, int>>();
foreach (var student in Students)
{
abstractInfo.Add(Tuple.Create(student.Name,student .Id));
}
return abstractInfo;
}





نكته : Tuple مي تواند براي بازگرداندن بيش از يك مقدار از تابع به كار رود. قبلا در سناريوهاي مشابه، براي بازگرداندن بيش از يك مقدار از تابع مي بايست از كلمه كليدي out براي آرگومان هاي ورودي كه در اصل حكم مقادير بازگشتي را داشتند، استفاده مي شد.

نوع جديد Lazy
در برخي موارد، ايجاد يك نوع خاص، امري پرهزينه است. به اين معنا كه پردازش و يا منابع زيادي درگير ايجاد شي ء شده و حدالامكان بايد از ايجاد غيرضروري اينگونه اشياء خودداري كرد. دات نت فريم ورك 4.0، كلاس جديدي به نام Lazy در فضاي نام System ارائه مي دهد كه راه حلي جامع و كامل براي سناريوهاي مشابه مي باشد. Lazy كلاسي جنريك بوده و مي تواند در رابطه با هر نوعي تعريف شود. كار كردن با اين كلاس بسيار ساده بوده چرا كه فقط شامل دو خصيصه IsValueCreated و Value مي باشد. نوع استفاده شده در تعريف Lazy، زماني مقداردهي مي شود كه خصيصه Value اولين بار فراخواني شود. به يك مثال ساده توجه كنيد:



using System;

namespace PdLazySample
{
class Program
{
static void Main()
{
Console.WriteLine("Before declaration");
var PdLazyResource = new Lazy<PdResource>(); // Lazy تعريف نوع


Console.WriteLine(PdLazyResource); Console.WriteLine("After declaration");
Console.WriteLine(PdLazyResource.Value); // دسترسي به مقدار و در نتيجه ايجاد آن

}
}


{
public PdResource()
{
Console.WriteLine("Start initialization");
}
}
}

class PdResource








خروجي حاصل از اين اجرا به شرح زير مي باشد:


Before declaration
After declaration
Value


is not created
Start initialization
PdLazySample.PdResource





با توجه به اين نكته از خصيصه IsValueCreated براي فهميدن اينكه شي ايجاد شده است يا نه استفاده مي شود.

Lazy به دو صورت ديگر نيز قابل مقداردهي ست كه عبارت اند از:

public Lazy(bool isThreadSafe);
public Lazy(Func<T> valueFactory, bool isThreadSafe);






ممكن است بخواهيم از Lazy در پردازش هاي چند ريسماني (Multi Threading) استفاده كنيم. در اين صورت اين سوال مطرح مي شود كه آيا شي مورد نظر در برابر دسترسي هاي چند ريسمان (Thread) ايمن مي باشد يا نه. اگر isThreadSafe مقدار true داشته باشد، تضميني ايجاد مي شود كه شي مورد نظر به ازاي دسترسي از چند ريسمان، فقط يك بار مقداردهي خواهد شد.
همچنين در برخي موارد هنگام ايجاد شي پرهزينه، ممكن است بخواهيم متغيرهايي را مقداردهي كنيم. در اين صورت مي توان با تعيين valueFactory اين كار را انجام داد:



namespace PdLazySample2
{
class Program
{
static void Main()
{
var PdLazyResource = new Lazy<PdResource>
( () =>
{
return new PdResource {ResourceName = "Static Resource"}; // مقداردهي يك خصيصه از كلاس مورد نظر

}
);
}
}


{
public string ResourceName { get; set; }

public PdResource()
{
}
}
}

class PdResource








ساختمان داده جديد SortedSet
اين ساختمان داده كه در فضاي نام System.Collections.Generic قرار دارد، يكي از انواع جديد در دات نت فريم ورك 4.0 مي باشد و همانطور كه از نام آن پيداست، مجموعه اي از عناصر مرتب شده را كه منحصر به فرد هم هستند، نگهداري مي كند. قبل از دات نت فريم ورك 4.0، HashSet براي نگهداري منحصر به فرد عناصر يك مجموعه به كار مي رفت كه SortedSet علاوه بر مرتب نگه داشتن عناصر، از كارايي بالايي برخوردار مي باشد.



class Program
{
static void Main()
{
SortedSet<int> sortedPdSet = new SortedSet<int> { 1, 5, 2, 4, 2, 15, 12, 1 };
foreach (int item in sortedPdSet)
{
Console.Write(item);
}
}
}





خروجي قطعه كد بالا، به صورت 1,2,4,5,12,15 بوده و اعضاي تكراري 1,2 فقط يكبار نمايش داده خواهند شد.
در استفاده از SortedSet مي توان با تعريف كلاس Comparer جديد از طريق ارث بري از IComparer، مقايسه عناصر را به دلخواه خود انجام داد.

BigInteger خيلي بزرگتر از نوع long!
تا قبل از دات نت فريم ورك 4.0 نوع (Int64 (long براي نگهداري مقادير بزرگ عددي به كار مي رفت. اما در بسياري از محاسبات پيچيده رياضي long نمي توانست جوابگوي نياز باشد و اجرا با مشكل مواجه مي شد. در فضاي نام System.Numerics، دات نت فريم ورك 4.0 نوع جديدي به نام BigInteger معرفي شده است كه مي تواند براي نگهداري مقادير خيلي خيلي بزرگ به كار رود. شايد اين سوال مطرح شود كه BigInteger چه كرانه اي براي نگهداري اعداد دارد؟ در پاسخ بايد گفت كه از نظر تئوري هيچ محدوديتي براي نگهداري اعداد توسط نوع BigInteger وجود ندارد و به همين خاطر است كه اين نوع، MinValue و MaxValue را شامل نمي شود. تنها محدوديت سر راه BigInteger مقدار حافظه سيستمي است كه برنامه بر روي آن اجرا مي شود. نكته ديگر در رابطه با نوع BigInteger اين است كه كلاس Math در فضاي نام System با اين نوع سازگار نمي باشد! در عوض تمامي توابع محاسباتي رياضي به صورت استاتيك توسط BigInteger فراهم شده اند. سري معروف فيبوناچي را با استفاده از BigInteger به صورت زير بازنويسي كرده ايم.



using System;
using System.Collections.Generic;
using System.Numerics;

namespace PdFibonaci
{
public class PdFibonacci
{
public static int PdClassicFibonacci(int x)
{
if (x <= 1)
return 1;
return PdClassicFibonacci(x - 1) + PdClassicFibonacci(x - 2);
}

public static IEnumerable<BigInteger> BigPdFib(Int64 toNumber)
{
BigInteger previous = 0;
BigInteger current = 1;

for (Int64 y = 1; y <= toNumber; y++)
{
var auxiliar = current;
current += previous;
previous = auxiliar;
yield return current;
}
}
}
}



فراخواني تابع جديد با استفاده از مقادير بسيار بزرگ مانند 10000 در كمترين زمان ممكن و كارايي بسيار بالايي انجام مي شود.

Memory-Mapped Files
آيا تاكنون با نياز تبادل اطلاعات بين دو پروسس برخورد كرده ايد؟ و يا اينكه فايل هاي حجيمي داشته باشيد كه نتوانسته ايد به يكباره آنها را در حافظه بارگذاري كرده و پردازش كنيد؟ دات نت فريم ورك 4.0 با ارائه فايل هاي نگاشت حافظه اي (Memory-Mapped Files) راه حلي جامع براي دو سناريوي ذكر شده ارائه كرده است. فايل هاي نگاشت حافظه اي اين امكان را در اختيار قرار مي دهند كه با اختصاص نامي خاص، بخشي از حافظه را در اختيار گرفته و مورد استفاده قرار دهيم. اين استفاده مي تواند نه تنها توسط پروسس ايجاد كننده، بلكه توسط ديگر پرسس ها نيز باشد. مزيت مهم فايل هاي نگاشت حافظه اي اين است كه مديريت آنها توسط سيستم عامل و paging انجام مي شود. paging يكي از مفاهيم سيستم عامل در مديريت حافظه است. تصور كنيد كه حافظه از قسمت هاي به نام page تشكيل شده است و pageهايي كه ديگر نيازي به وجود آنها در حافظه نباشد، توسط سيستم عامل از حافظه خارج شده و pageهايي ديگر جايگزين آنها مي شوند. با توجه به توضيحات فوق، فايل هاي نگاشت حافظه اي در دو سناريو بسيار مفيد خواهند بود:



ارتباط بين پروسس ها (inter-process communication)

شكستن فايل هاي حجيم به قسمت هاي كوچك تر و بارگذاري مجزاي هر قسمت به حافظه جهت پردازش و استفاده



كلاس MemoryMappedFile در فضاي نام System.IO.MemoryMappedFiles واقع شده است. براي استفاده از آن ابتدا بايد يك نمونه (instance) اسمي فايل نگاشت حافظه اي ايجاد كرد. با استفاده از يكي از چهار تابع استاتيك زير مي توان اين كار را انجام داد:


CreateFromFile
CreateNew
CreateOrOpen
OpenExisting







مقدار فضاي منطقي حافظه براي هر پروسس در سيستم هاي 32 بيتي 2 گيگابايت است. چنانچه براي نگاشت فايل به بيش از اين مقدار نياز باشد، بايد بيش از يك نمونه (instance) ايجاد كرد. پس از اين مرحله، با فراخواني يكي از دو تابع CreateViewStream يا CreateViewAccessor مي توان به فضاي فايل نگاشت حافظه اي دسترسي پيدا كرد. CreateViewStream مقداري از نوع MemoryMappedFileViewStream برمي گرداند كه مي توان مانند ساير Stream هاي دات نت فريم ورك از آن استفاده كرد. مقدار بازگشتي CreateViewAccessor نيز از نوع MemoryMappedFileViewAccessor مي باشد. قابل ذكر است دسترسي به اطلاعات در حالت اول از نوع ترتيبي و در حالت دوم از نوع تصادفي است.
بحث فايل هاي نگاشت حافظه اي را با يك مثال به پايان مي بريم. فرض كنيد كه پروسسي يك فايل نگاشت حافظه اي به شكل زير ايجاد كند:



static void Main()
{
using (var memoryMappedFile = MemoryMappedFile.CreateNew("PdMemoryMappdFile", 1000)) //ايجاد فايل نگاشت حافظه اي

{
// باز كردن يك استريم براي دسترسي به فضاي نگاشت حافظه اي

{

writer.Write("Pd says hello memory mapped file!"); var writer = new BinaryWriter(stream);// نوشتن اطلاعات در فضاي نگاشت حافظه از طريق استريم باز شده
}
}
}

using (var stream = memoryMappedFile.CreateViewStream())


حال پروسس ديگري مي تواند به اطلاعات نوشته شده توسط پروسس اول به شكل زير دسترسي داشته باشد:



static void Main()
{
using (var memoryMappedFile = MemoryMappedFile.OpenExisting("PdMemoryMappdFile") ) // باز كردن فايل نگاشت حافظه اي ايجاد شده توسط پروسس قبلي

// باز كردن يك استريم براي دسترسي به فضاي نگاشت حافظه اي

{

Console.WriteLine(reader.ReadString()); var reader = new BinaryReader(stream);// خواندن اطلاعات از استريم باز شده

}
}

using (var stream = memoryMappedFile.CreateViewStream()




منبع (http://www.persiadevelopers.com/articles/framework4-new-structures.aspx)