۱۳۸۹/۰۳/۱۰

تقويم فارسي و سيلورلايت؛ لطفا راي بدهيد!


سيلورلايت 4 با پشتيباني رسمي از زبان‌هاي راست به چپ و همچنين ارائه‌ي كوهي از قابليت‌هاي جديد، كانديد مناسبي براي توسعه‌ي نرم افزارهاي تحت وب (و همچنين برنامه‌هاي Desktop چند سكويي) مي‌باشد. اما بايد درنظر داشت كه تيم آن براي كوچك نگه داشتن حجم افزونه‌ي آن تمامي كلاس‌هاي موجود در دات نت فريم ورك را به آن اضافه نكرده‌اند و تقويم فارسي نيز از اين دست است.
مايكروسافت مدتي است كه قسمتي را جهت دريافت بازخورد برنامه نويس‌ها و دريافت نظرات و پيشنهادات آن‌ها در اين مورد ايجاد كرده است:


در همين زمينه لطفا به آدرس ذيل مراجعه كرده و براي اضافه شدن تقويم فارسي به صورت رسمي به آن راي بدهيد؛ با تشكر!



سيلورلايت بر روي كدام سكوهاي كاري قابل اجرا است؟


تاكنون سيلورلايت به سكوهاي كاري مختلفي منتقل شده است و با توجه به مزاياي استفاده از يك نسخه‌ي ساده شده‌ي دات نت فريم ورك (براي اينكه حجم افزونه‌ي آن زياد نشود)، فراهم بودن اكثر امكانات طرح بندي WPF در آن، امكان استفاده از همان زبان‌هاي آشناي دات نت مانند CS و VB براي توسعه‌ي Silverlight، امكان اجراي برنامه‌هاي آن در خارج از مرورگر همانند يك برنامه‌ي Desktop (البته با قيود امنيتي بسيار زياد)، امكان دسترسي كامل به وب سرويس‌ها و امكانات WCF، اين روزها كم كم دارد جاي بسياري از فناوري‌هاي دهه‌ي قبل را مي‌گيرد و حداقل اگر به ليست تازه‌هاي VS.NET 2010 و موارد مرتبط به آن دقت كنيم، Silverlight جزو مواردي است كه بيشترين حجم توجه و نو‌آوري را به خود اختصاص داده است.
در ادامه ليستي از سكوهاي كاري را كه سيلورلايت به آن‌ها منتقل شده است يا خواهد شد، با هم مرور خواهيم كرد:
- ويندوز : +
- ويندوز مدفون شده : +
- ويندوز فون 7 : +
- Macintosh OS 10.4.11+ Intel-based : + و + (جالب اينجا است كه از طرف خود مايكروسافت پشتيباني مي‌شود)
- لينوكس : +
- تلاش اينتل براي انتقال به لينوكس : +
- Xbox 360 : +
- سيمبين: + و +

۱۳۸۹/۰۳/۰۹

درسي از بروسلي در توسعه‌ي نرم افزار!


نقل قولي از بروسلي:
The style doesn’t make the fighter, the fighter makes the style.

معادل آن در دنياي نرم افزار:
The process doesn’t make the developer, the developer makes the process.

معنا:
پيروي كوركورانه از روش‌ها و شيوه‌هاي جديد از شما برنامه نويس نخواهد ساخت! "شما" هستيد كه به كار معنا خواهيد داد.
تمركز بيش از حد بر روي يك روش كاري، ديدگاه شما را محدود ساخته و از بسياري از موقعيت‌ها و امكانات مهياي ديگر غافل خواهيد شد.

ادامه مطلب :
Bruce Lee on Software Development

۱۳۸۹/۰۳/۰۴

منسوخ شده‌ها در دات نت 4


براي كاهش حجم دات نت در نگارش‌هاي بعدي، كلاس‌هايي كه توسط تيم‌هاي مختلف پيشتر توسعه يافته بودند، اكنون با هم تلفيق شده و نظم بهتري پيدا كرده‌اند. براي مثال كليه كلاس‌هاي مرتبط با زبان‌هاي اسكريپتي اكنون به فضاي نام System.CodeDom.Compiler.ICodeCompiler منتقل شده‌اند و غيره. مرجع نسبتا مفصلي در مورد منسوخ شده‌ها در دات نت 4 اخيرا منتشر شده است:

و حتما مي‌دانيد كه چگونه يك متد يا نوع را بايد به صورت منسوخ شده معرفي كرد:

در اين حالت هنگام كامپايل برنامه، پيغام اخطاري توسط كامپايلر صادر خواهد شد.

۱۳۸۹/۰۲/۲۹

اندكي به روز رساني


ليست وبلاگ‌هاي آي تي ايراني را به روز كردم كه فايل OPML آن از اينجا و همچنين از طريق لينك آن در منوي سمت راست سايت قابل دريافت است.
اين ليست بر اساس يافته‌هاي من از سايت‌هاي به اشتراك گذاري لينك‌هاي ايراني است مانند : idevcenter.com و mohand.es . اگر آدرس وبلاگ شما در اين ليست قرار ندارد لطفا يكبار در يكي از اين دو سايت آدرس مطالب خود را منتشر كنيد. با تشكر


۱۳۸۹/۰۲/۲۷

مروري بر چند تجربه‌ي كاري با SQLite





SQLite بانك اطلاعاتي سريع، كم حجم و سورس بازي است كه استفاده از آن در دات نت فريم ورك بسيار ساده است. فقط كافي است پروايدر مربوط به آن را دريافت كنيد و در كدهاي قديمي خود هر جايي مثلا sqlconnection داشتيد آن‌را تبديل به sqliteconnection كنيد و امثال آن (به بيان ديگر، پروايدر تهيه شده از معماري ADO.NET پيروي مي‌كند و عملا دانش قبلي شما به سادگي قابل استفاده و ارتقاء است). علاوه بر آن پروايدر ADO.NET‌ تهيه شده براي آن، پشتيباني از Entity framework را هم ارائه مي‌دهد.
اين ديتابيس تحت سيستم عامل‌هاي مختلف مهيا است و مهم‌ترين مزيت آن عدم نياز به نصب آن مي‌باشد.

مزايا:
- سورس باز و رايگان
- مهيا بودن آن در ساير پلتفرم‌ها (ويندوز، لينوكس و ...)
- نيازي به نصب ندارد و فقط يك DLL بومي است. اين مورد براي كاربراني كه در مديريت بانك‌هاي اطلاعاتي پيچيده مشكل دارند، يك مزيت مهم است.
- امكان تشيكل ديتابيس در حافظه. اين نكته و توانايي، در آزمون‌هاي واحد بسيار جالب توجه است. مي‌توانيد با سرعت بالا ديتابيسي واقعي را در حافظه تشكيل داده، كليه آزمون‌هاي واحد خود را اجرا كرده و پس از پايان كار، اثري از ديتابيس و تغيير داده‌ها و مشكلات بازگرداني اطلاعات به حالت اول وجود نخواهد داشت.


ملاحظات:
الف) مرتب سازي SQLite حساس به حروف كوچك و بزرگ است.
براي برگشت به عادت متداولي كه وجود دارد مي‌شود به صورت زير عمل كرد:
select f1 from tbl1 order by f1 COLLATE NOCASE
يك COLLATE NOCASE اضافه شده است.

ب) رعايت نكات مرتبط با سيستم‌هاي 64 بيتي
در مورد سيستم‌هاي 64 بيتي و دات نت قبلا مطلبي را نوشته بودم : {+}. اين مطلب دقيقا اينجا كاربرد پيدا مي‌كند، از اين لحاظ كه SQLite يك بانك اطلاعاتي Native است. اگر برنامه‌ي دات نت شما براي حالت Any CPU تهيه شده است، در سيستم‌هاي 32 بيتي نياز است تا DLL مرتبط SQLite را توزيع كنيد و در سيستم‌هاي 64 بيتي DLL مرتبط 64 بيتي آن نياز خواهد بود. در غيراينصورت برنامه‌ي شما در بدو امر كرش كرده و اجرا نخواهد شد.

مشكلات:
الف) كليد خارجي بي خاصيت!
SQLite از كليد خارجي پشتيباني مي‌كند اما آن‌را اعمال نمي‌كند! براي اينكه كليد خارجي را اعمال كنيد بايد خودتان تريگر بنويسيد تا اين‌كار را انجام دهد.

ب) پشتيباني در حد صفر از مباحث همزماني و تردينگ.
اگر برنامه شما مالتي ترد است، در بد مخمصه‌اي گرفتار شده‌ايد. مدام با پيغام database is locked مواجه خواهيد شد. (چه انتظاري داشتيد؟ يك dll كمتر از 2 مگابايت كه قرار نيست كار غول‌هاي ديتابيسي را انجام دهد)
بنابراين اصلا تصورش را هم نكنيد كه از اين ديتابيس به عنوان بانك اطلاعاتي يك سايت (و محيط‌هاي چند كاربره) بتوان استفاده كرد و كاربران دچار مشكل نشوند.

ج)حجم بالاي ديتابيس و عدم كش
از مباحث caching كه در ديتابيس‌هاي معظم ديگر به صورت توكار وجود دارد خبري نيست. براي مثال اگر يك كوئري قرار است تعدادي را شمارش نمايد، حاصلي كش نشده و اگر صدبار هم به صورت متوالي آن‌را فراخواني كنيد باز هم از نو محاسبات آن انجام خواهد شد.
اين مورد در حجم بالاي ديتابيس واقعا مهم است و نمودش را با ديتابيسي با حجم بالاي يك گيگ به وضوح مشاهده خواهيد. افت كارآيي و همچنين قرچ و قرچ مداوم هارد ديسك سيستم! (چون به كش رجوع نمي‌شود)

د) امنيت
روي بانك‌هاي اطلاعاتي اكسس حداقل مي‌توان يك كلمه‌ي عبور را قرار داد (كه در كسري از ثانيه قابل شكستن است!). در SQLite استاندارد هيچ خبري از اين مباحث نبوده و امنيت را بايد خودتان تامين كنيد. (البته يك نسخه‌ي تجاري هم از اين بانك اطلاعاتي با پشتيباني از رمزنگاري اطلاعات موجود است : +)

ه) مرتب سازي فارسي
هر چند SQLite هيچ مشكلي در ثبت اطلاعات يونيكد و خصوصا متون فارسي ندارد، اما با مرتب سازي كلمات يونيكد مشكل داشته و بر اساس كد اسكي آن‌ها عمل مي‌كند. هر چند امكان تعريف Collation سفارشي در آن ممكن است : + (البته ممكن بودن با موجود بودن متفاوت است)


نتيجه گيري:
- SQLite براي ديتابيسي تا حدود يك گيگ كه فقط يك نفر قرار باشد از آن استفاده كند انتخاب بسيار مناسبي است (براي مثال فايرفاكس از آن براي ذخيره سازي تنظيمات خودش استفاده مي‌كند).

۱۳۸۹/۰۲/۲۶

SortedSet در دات نت 4


SortedSet قرار گرفته در فضاي نام System.Collections.Generic دات نت 4، ليستي از اشياء به صورت خودكار مرتب شده را ارائه مي‌دهد. SortedSet نيز همانند HashSet از اعضاي منحصربفردي تشكيل خواهد شد اما اينبار به شكلي مرتب شده. براي پياده سازي آن از red-black tree data structure استفاده شده است كه مهم‌ترين مزيت آن امكان افزودن و يا حذف اشياء به آن بدون كاهش قابل توجه كارآيي برنامه است.

مثال اول:
using System;
using System.Collections.Generic;

namespace SortedSetTest
{
class Program
{
static void sample1()
{
var setRange = new SortedSet<int> { 2, 5, 6, 2, 1, 4, 8 };

foreach (var i in setRange)
{
Console.WriteLine(i);
}
}

static void Main()
{
sample1();
}
}
}
در اين مثال با نحوه‌ي ايجاد اين ليست جنريك خود مرتب شونده‌ي تكراري نپذير (!) آشنا مي‌شويد. اگر اين مثال را اجرا نمائيد، خروجي آن مرتب شده است و همچنين تنها شامل يك عدد 2 است (اعضاي تكراري را حذف مي‌كند).

مثال دوم:

using System;
using System.Collections.Generic;

namespace SortedSetTest
{
class Program
{
static void sample2()
{
var setRange = new SortedSet<int>();
var random = new Random();

for (int counter = 0; counter < 100; counter++)
{
var rnd = random.Next(-180, 181);
if (!setRange.Add(rnd))
{
Console.WriteLine("Couldn't add {0}", rnd);
}
}

Console.WriteLine("Result set:");
foreach (var item in setRange)
{
Console.WriteLine(item);
}
}

static void Main()
{
sample2();
}
}
}
در اين مثال نحوه‌ي افزودن اعضاي مختلف به اين ليست ويژه، توسط متد Add آن بيان شده است. اگر آيتمي در اين ليست موجود باشد، مجددا اضافه نشده و حاصل متد Add آن، False خواهد بود.

مثال سوم:
اگر از ساير انواع سفارشي تعريف شده استفاده نمائيد، بايد روش مقايسه‌ي آن‌ها را نيز با پياده سازي اينترفيس استاندارد IComparable ارائه دهيد؛ در غير اينصورت با خطاي At least one object must implement IComparable متوقف خواهيد شد.

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

namespace SortedSetTest
{
class FileInfo
{
public string Name { set; get; }
public long Size { set; get; }
}

class FileInfoComparer : IComparer<FileInfo>
{
public int Compare(FileInfo x, FileInfo y)
{
var caseiComp = new CaseInsensitiveComparer();
return caseiComp.Compare(x.Name, y.Name);
}
}


class Program
{

static void sample3()
{
var setRange = new SortedSet<FileInfo>(new FileInfoComparer())
{
new FileInfo
{
Name = "file1.txt",
Size = 100
},
new FileInfo
{
Name = "file2.txt",
Size = 10
},
new FileInfo
{
Name = "file3.txt",
Size = 300
}
};

foreach (var item in setRange)
{
Console.WriteLine(item.Name);
}
}

static void Main()
{
sample3();

Console.WriteLine("Press a key...");
Console.ReadKey();
}
}
}

در اين مثال اشيايي از نوع كلاس FileInfo به ليست ويژه‌ي ما اضافه شده‌اند. براي اينكه امكان مقايسه‌ي آن‌ها فراهم باشد ، كلاس FileInfoComparer با پياده سازي اينترفيس IComparer ، روش مقايسه دو شيء از اين دست را ارائه مي‌دهد.

۱۳۸۹/۰۲/۲۴

ليستي از بانك‌هاي اطلاعاتي قابل استفاده در دات نت


بد نيست ليست تعدادي از بانك‌هاي اطلاعاتي مهم قابل استفاده در دات نت به همراه درايورهاي ADO.NET آن‌ها را با هم مرور نمائيم.

بانك‌هاي اطلاعاتي قابل استفاده در دات نت فريم ورك

رديف
بانك اطلاعاتي سايت مرجع درايور ADO.NET امكان استفاده از LINQ مجوز استفاده
توضيحات
1 SQL Server 2000/2005/2008/2008 R2 + توكار (به صورت پيش فرض در دات نت فريم ورك موجود است) بلي . به كمك LINQ to SQL ،
Entity Framework ، NHibernate و بسياري از ORM هاي ديگر
رايگان - تجاري نسخه‌‌هاي Express آن رايگان است.
2 Microsoft SQL Azure + بلي :
+
بلي. به كمك LINQ to SQL و
Entity Framework
تجاري
3 SQL Server Compact + بلي :

+
بلي. به كمك LINQ to SQL و
Entity Framework
رايگان
4 Advantage Database Server
+
قابل دريافت از سايت اصلي:

+
بلي. به كمك Entity framework و
Telerik OpenAccess
ORM
تجاري
5 SQL Anywhere
+
قابل دريافت از سايت اصلي:
+
بلي. به كمك Entity framework
و Telerik
OpenAccess ORM
رايگان - تجاري
Web Edition
آن رايگان است.
6 MySQL + قابل دريافت از سايت اصلي :
+
بلي . به كمك
NHibernate
،
LightSpeed
، DbLinq و تعدادي ديگر از
ORM's
رايگان - تجاري
7 Oracle + پشتيباني توكار آن به زودي
حذف
خواهد شد
اما از سايت اصلي قابل دريافت است :
+
بلي . به كمك
NHibernate
،
LightSpeed
، DbLinq و تعدادي ديگر از
ORM's
رايگان - تجاري نسخه‌ي Express آن رايگان است.
8 Access + توكار بلي. به كمك ALinq ،

NHibernate
و يا
LINQ to
DataSets
تجاري اگر از دات نت فريم ورك سه و نيم، سرويس پك يك استفاده كنيد، امكان
استفاده از LINQ to SQL جهت كار با بانك‌هاي
اطلاعاتي اكسس نيز مهيا است:

+
9 SQLite + مهيا به صورت سورس باز :
+
بلي. درايور ADO.NET آن پشتيباني از Entity
Framework را نيز اضافه مي‌كند. همچنين NHibernate
،
ALinq
و ساير ORM's را بايد به اين ليست اضافه كرد.
رايگان
10 Firebird + قابل دريافت از سايت اصلي: ‌+ بلي. توسط ALinq ،
NHibernate
و موارد ديگر.
رايگان
11 PostgreSQL + قابل دريافت از سايت اصلي:
+
بلي. توسط NHibernate ، DBLinq و موارد ديگر رايگان
12 DB2 UDB + قابل دريافت از سايت اصلي:
+
بلي. توسط NHibernate تجاري
13 ScimoreDB + قابل دريافت از سايت اصلي:
+
محدود. توسط
LINQ to DataSets
رايگان
14 MongoDB + معرفي شده در سايت اصلي :
+
بلي. درايور ADO.NET معرفي شده به همراه
پروايدر LINQ نيز مي‌باشد.
رايگان
15 CouchDB + معرفي شده در سايت اصلي :
+
محدود رايگان
16 VistaDB + اساسا براي دات نت نوشته شده است. بلي. به كمك
Entity framework
تجاري


۱۳۸۹/۰۲/۲۰

دات نت 4 و كلاس Lazy


يكي از الگوهاي برنامه نويسي شيء گرا، Lazy Initialization Pattern نام دارد كه دات نت 4 پياده سازي آن‌را سهولت بخشيده است.
در دات نت 4 كلاس جديدي به فضاي نام System اضافه شده است به نام Lazy و هدف از آن lazy initialization است؛ من ترجمه‌اش مي‌كنم وهله سازي با تاخير يا به آن on demand construction هم گفته‌اند (زماني كه به آن نياز هست ساخته خواهد شد).
فرض كنيد در برنامه‌ي خود نياز به شيءايي داريد و ساخت اين شيء بسيار پرهزينه است. نيازي نيست تا بلافاصله پس از تعريف، اين شيء ساخته شود و تنها زمانيكه به آن نياز است بايد در دسترس باشد. كلاس Lazy جهت مديريت اينگونه موارد ايجاد شده است. تنها كاري كه در اينجا بايد صورت گيرد، محصور كردن آن شيء هزينه‌بر توسط كلاس Lazy است:

Lazy<ExpensiveResource> ownedResource = new Lazy<ExpensiveResource>();

در اين حالت براي دسترسي به شيء ساخته شده از ExpensiveResource ، مي‌توان از خاصيت Value استفاده نمود (ownedResource.Value). تنها در حين اولين دسترسي به ownedResource.Value ، شيء ExpensiveResource ساخته خواهد شد و نه پيش از آن و نه در اولين جايي كه تعريف شده است. پس از آن اين حاصل cache شده و ديگر وهله سازي نخواهد شد.
ownedResource داراي خاصيت IsValueCreated نيز مي‌باشد و جهت بررسي ايجاد آن شيء مي‌تواند مورد استفاده قرار گيرد. براي مثال قصد داريم اطلاعات ExpensiveResource را ذخيره كنيم اما تنها در حالتيكه يكبار مورد استفاده قرار گرفته باشد.
كلاس Lazy داراي دو متد سازنده‌ي ديگر نيز مي‌باشد:
public Lazy(bool isThreadSafe);
public Lazy(Func<T> valueFactory, bool isThreadSafe);

و هدف از آن استفاده‌ي صحيح از اين متد در محيط‌هاي چند ريسماني است. بديهي است در اين نوع محيط‌ ها علاقه‌اي نداريم كه در يك لحظه توسط چندين ترد مختلف، سبب ايجاد وهله‌هاي ناخواسته‌ا‌ي از ExpensiveResource شويم و تنها يك مورد از آن كافي است يا به قولي thread safe, lazy initialization of expensive objects
بديهي است اگر برنامه‌ي شما چند ريسماني نيست مي‌توانيد اين مكانيزم را كنسل كرده و اندكي كارآيي برنامه را با حذف قفل‌هاي همزماني اين كلاس بالا ببريد.

مثال اول:

using System;
using System.Threading;

namespace LazyExample
{
class Program
{
static void Main()
{
Console.WriteLine("Before assignment");
var slow = new Lazy<Slow>();
Console.WriteLine("After assignment");

Thread.Sleep(1000);

Console.WriteLine(slow);
Console.WriteLine(slow.Value);

Console.WriteLine("Press a key...");
Console.Read();
}
}


class Slow
{
public Slow()
{
Console.WriteLine("Start creation");
Thread.Sleep(2000);
Console.WriteLine("End creation");
}
}
}
خروجي اين برنامه به شرح زير است:

Before assignment
After assignment
Value is not created.
Start creation
End creation
LazyExample.Slow
Press a key...

همانطور كه ملاحظه مي‌كنيد تنها در حالت دسترسي به مقدار Value شيء slow ، عملا وهله‌اي از آن ساخته خواهد شد.

مثال دوم:
شايد نياز به مقدار دهي خواص كلاس پرهزينه‌ وجود داشته باشد. براي مثال علاقمنديم خاصيت SomeProperty كلاس ExpensiveClass را مقدار دهي كنيم. براي اين منظور مي‌توان به شكل ذيل عمل كرد (يك Func<t>را مي‌توان به سازنده‌ي آن ارسال نمود):

using System;

namespace LazySample
{
class Program
{
static void Main()
{
var expensiveClass =
new Lazy<ExpensiveClass>
(
() =>
{
var fobj = new ExpensiveClass
{
SomeProperty = 100
};
return fobj;
}
);

Console.WriteLine("expensiveClass has value yet {0}",
expensiveClass.IsValueCreated);

Console.WriteLine("expensiveClass.SomeProperty value {0}",
(expensiveClass.Value).SomeProperty);

Console.WriteLine("expensiveClass has value yet {0}",
expensiveClass.IsValueCreated);

Console.WriteLine("Press a key...");
Console.Read();
}
}

class ExpensiveClass
{
public int SomeProperty { get; set; }

public ExpensiveClass()
{
Console.WriteLine("ExpensiveClass constructed");
}
}
}

كاربردها:
- علاقمنديم تا ايجاد يك شيء هزينه‌بر تنها پس از انجام يك سري امور هزينه‌بر ديگر صورت گيرد. براي مثال آيا تابحال شده است كه با يك سيستم ماتريسي كار كنيد و نياز به چند گيگ حافظه براي پردازش آن داشته باشيد؟! زمانيكه از كلاس Lazy استفاده نمائيد، تمام اشياء مورد استفاده به يكباره تخصيص حافظه پيدا نكرده و تنها در زمان استفاده از آن‌ها كار تخصيص منابع صورت خواهد گرفت.
- ايجاد يك شيء بسيار پر هزينه بوده و ممكن است در بسياري از موارد اصلا نيازي به ايجاد و يا حتي استفاده از آن نباشد. براي مثال يك شيء كارمند را درنظر بگيريد كه يكي از خواص اين شيء، ليستي از مكان‌هايي است كه اين شخص قبلا در آنجاها كار كرده است. اين اطلاعات نيز به طور كامل از بانك اطلاعاتي دريافت مي‌شود. اگر در متدي، استفاده كننده از شيء كارمند هيچگاه اطلاعات مكان‌هاي كاري قبلي او را مورد استفاده قرار ندهد، آيا واقعا نياز است كه اين اطلاعات به ازاي هر بار ساخت وهله‌اي از شيء كارمند از ديتابيس دريافت شده و همچنين در حافظه ذخيره شود؟

۱۳۸۹/۰۲/۱۷

Tuple در دات نت 4


نوع جديدي در دات نت 4 به نام Tuple اضافه شده است كه در اين مطلب به بررسي آن خواهيم پرداخت.
در رياضيات، Tuple به معناي ليست مرتبي از اعضاء با تعداد مشخص است. Tuple در زبان‌هاي برنامه نويسي Dynamic مانند اف شارپ، Perl ، LISP و بسياري موارد ديگر مطلب جديدي نيست. در زبان‌هاي dynamic برنامه نويس‌ها مي‌توانند متغيرها را بدون معرفي نوع آن‌ها تعريف كنند. اما در زبان‌هاي Static مانند سي شارپ، برنامه نويس‌ها موظفند نوع متغيرها را پيش از كامپايل آن‌ها معرفي كنند كه هر چند كار كد نويسي را اندكي بيشتر مي‌كند اما به اين صورت شاهد خطاهاي كمتري نيز خواهيم بود (البته سي شارپ 4 اين مورد را با معرفي واژه‌ي كليدي dynamic تغيير داده است).
براي مثال در اف شارپ داريم:
let data = (“John Doe”, 42)

كه سبب ايجاد يك tuple كه المان اول آن يك رشته و المان دوم آن يك عدد صحيح است مي‌شود. اگر data را بخواهيم نمايش دهيم خروجي آن به صورت زير خواهد بود:
printf “%A” data
// Output: (“John Doe”,42)

در دات نت 4 فضاي نام جديدي به نام System.Tuple معرفي شده است كه در حقيقت ارائه دهنده‌ي نوعي جنريك مي‌باشد كه توانايي در برگيري انواع مختلفي را دارا است :
public class Tuple<T1>
up to:
public class Tuple<T1, T2, T3, T4, T5, T6, T7, TRest>

همانند آرايه‌ها، اندازه‌ي Tuples نيز پس از تعريف قابل تغيير نيستند (immutable). اما تفاوت مهم آن با يك آرايه در اين است كه اعضاي آن مي‌توانند نوع‌هاي كاملا متفاوتي داشته باشند. همچنين تفاوت مهم آن با يك ArrayList يا آرايه‌اي از نوع Object، مشخص بودن نوع هر يك از اعضاء آن است كه type safety بيشتري را به همراه خواهد داشت و كامپايلر مي‌تواند در حين كامپايل دقيقا مشخص نمايد كه اطلاعات دريافتي از نوع صحيحي هستند يا خير.

يك مثال كامل از Tuples را در كلاس زير ملاحظه خواهيد نمود:

using System;
using System.Linq;
using System.Collections.Generic;

namespace TupleTest
{
class TupleCS4
{
#region Methods (4)

// Public Methods (4)

public static Tuple<string, string> GetFNameLName(string name)
{
if (string.IsNullOrWhiteSpace(name))
throw new NullReferenceException("name is empty.");

var nameParts = name.Split(',');

if (nameParts.Length != 2)
throw new FormatException("name must contain ','");

return Tuple.Create(nameParts[0], nameParts[1]);
}

public static void PrintSelectedTuple()
{
var list = new List<Tuple<string, int>>
{
new Tuple<string, int>("A", 1),
new Tuple<string, int>("B", 2),
new Tuple<string, int>("C", 3)
};

var item = list.Where(x => x.Item2 == 2).SingleOrDefault();
if (item != null)
Console.WriteLine("Selected Item1: {0}, Item2: {1}",
item.Item1, item.Item2);
}

public static void PrintTuples()
{
var tuple1 = new Tuple<int>(12);
Console.WriteLine("tuple1 contains: item1:{0}", tuple1.Item1);

var tuple2 = Tuple.Create("Item1", 12);
Console.WriteLine("tuple2 contains: item1:{0}, item2:{1}",
tuple2.Item1, tuple2.Item2);

var tuple3 = Tuple.Create(new DateTime(2010, 5, 6), "Item2", 20);
Console.WriteLine("tuple3 contains: item1:{0}, item2:{1}, item3:{2}",
tuple3.Item1, tuple3.Item2, tuple3.Item3);
}

public static void Tuple8()
{
var tup =
new Tuple<int, int, int, int, int, int, int, Tuple<int, int>>
(1, 2, 3, 4, 5, 6, 7, new Tuple<int, int>(8, 9));

Console.WriteLine("tup.Rest Item1: {0}, Item2: {1}",
tup.Rest.Item1,tup.Rest.Item2);
}

#endregion Methods
}
}

using System;

namespace TupleTest
{
class Program
{
static void Main()
{
var data = TupleCS4.GetFNameLName("Vahid, Nasiri");
Console.WriteLine("Data Item1:{0} & Item2:{1}",
data.Item1, data.Item2);

TupleCS4.PrintTuples();

TupleCS4.PrintSelectedTuple();

TupleCS4.Tuple8();

Console.WriteLine("Press a key...");
Console.ReadKey();
}
}
}

توضيحات :
- روش‌هاي متفاوت ايجاد Tuples را در متد PrintTuples مي‌توانيد ملاحظه نمائيد. همچنين نحوه‌ي دسترسي به مقادير هر كدام از اعضاء نيز مشخص شده است.
- كاربرد مهم Tuples در متد GetFNameLName نمايش داده شده است؛ زمانيكه نياز است تا چندين خروجي از يك تابع داشته باشيم. به اين صورت ديگر نيازي به تعريف آرگومان‌هايي به همراه واژه كليدي out نخواهد بود يا ديگر نيازي نيست تا يك شيء جديد را ايجاد كرده و خروجي را به آن نسبت دهيم. به همان سادگي زبان‌هاي dynamic در اينجا نيز مي‌توان يك tuple را ايجاد و استفاده كرد.
- بديهي است از Tuples در يك ليست جنريك و يا حالات ديگر نيز مي‌توان استفاده كرد. مثالي از اين دست را در متد PrintSelectedTuple ملاحظه خواهيد نمود. ابتدا يك ليست جنريك از Tuple ايي با دو عضو تشكيل شده است. سپس با استفاده از امكانات LINQ ، عضوي كه آيتم دوم آن مساوي 2 است يافت شده و سپس المان‌هاي آن نمايش داده مي‌شود.
- نكته‌ي ديگري را كه حين كار با Tuples مي‌توان در نظر داشت اين است كه اعضاي آن حداكثر شامل 8 عضو مي‌توانند باشند كه عضو آخر بايد يك Tuple تعريف گردد و بديهي است اين Tuple‌ نيز مي‌تواند شامل 8 عضو ديگر باشد و الي آخر كه نمونه‌اي از آن را در متد Tuple8 مي‌توان مشاهده كرد.

۱۳۸۹/۰۲/۱۴

املاي صحيح فناوري‌هاي مرتبط با مايكروسافت


به نظر شما .net درست است يا .Net يا ... ؟
Asp.net چطور؟ آيا ASP.Net درست است يا Asp.net يا ... ؟!
Direct X درست است يا Direct-X يا ... ؟
Linq درست است يا linq يا ...؟

پاسخ: هيچكدام!
املاي تمامي موارد ذكر شده نادرست است. جدولي را يكي از كاركنان مايكروسافت در اين زمينه تهيه كرده است كه در آدرس ذيل مي‌توانيد مشاهده نمائيد: