نکاتی در مورد ارائه بصری اطلاعات
D3 6.0 منتشر شد
D3 6.0: The Data-Driven Document Library — The popular data visualization library takes a step forward by switching out a few internal dependencies for better alternatives, adopts ES2015 (a.k.a. ES6) internally, and now passes events directly to listeners. There’s also a 5.x to 6.0 migration guide for existing users.
یازده. در جاوا رویدادها با استفاده از اینترفیسها پیاده سازی میشوند. برای نامگذاری یک رویداد، قاعده آن در جاوا بدین شکل است که نامها به صورت (+ ) Camel نوشته شده و آخرین عبارت هم Listener باشد و نیازی هم به حرف I در نامگذاری اینترفیس نیست؛ چون همه میدانند که این Listener آخری یعنی رویدادی که با اینترفیس پیاده سازی شده است و استفاده از I بی معنی است. هر چند بر خلاف دات نت، در اینجا استفاده از قاعده I چندان متداول نیست.
public interface CopyFileListener { void PublishProgress(long fileSize,long copiedSize); }
دوازده. گوگل اینترفیسهایی را که برای رویدادها میسازد، داخل کلاس اصلی تعریف میکند. پس بهتر هست که شما هم همین روند را ادامه بدید و از این قاعده خارج نشوید. اگر خوب دقت کرده باشید، در برنامه نویسی اندروید تمام اینترفیسها داخل کلاس اصلی هستند:
textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } });
public class MemoryWare { public interface CopyFileListener { void PublishProgress(long fileSize,long copiedSize); } .... }
SetOnClickListener
editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { } });
سیزده. آداپتورها و آداپتور ویوها (چون لیست) قسمت مهمی از برنامههای اندرویدی به شمار میآیند؛ تا حدی که در بیشتر برنامههای ساده هم حضور پررنگی دارند. ولی برای استفاده از این آداپتورها باید بدانید که نحوه کار آنها چگونه است. بسیاری از کاربران در این قسمت اشتباهات زیادی میکنند. اگر در stackOverflow هم در اینباره نگاه کنید، با حجم انبوهی از سوالات روبرو میشوید و فقط به خاطر اینکه نحوه کارکرد آن را نمیدانند، به مشکل برخوردهاند.
کلاس BaseAdapter اصلیترین کلاس آداپتور هاست که بقیه از آن مشتق شدهاند و معروفترین مشتقات آن، کلاسهای CursorAdapter و ArrayAdapter هستند که امکانات بیس آداپتور را افزایش دادهاند.به عنوان مثال در کد پایین از ArrayAdapter استفاده شده است.
نحوه کار یک آداپتور بدین صورت است که متدی را به نام GetView با قابلیت override دارد که با هر تعداد آیتم موجود صدا زده میشود. ولی اگر تصور کنیم فقط چند صدهزار آیتم هم داشته باشیم، آیا واقعا اجرا میشود؟ جواب این سوال این است که با هر بار اسکرولی که شما میکنید آیتمهای بعدی ایجاد میشوند ولی باز این سوال پیش میآید که هر آیتم برای خود جداگانه تشکیل میشود؟ مطمئنا جواب خیر است. آداپتورها از سیستمی به نام ViewRecycler برای کش کردن آیتمهای ایجاد شده استفاده میکنند و با هر اسکرولی که انجام میشود آیتمهای بعدی از روی آیتمهای قبلی که قبلا از صفحه خارج شدهاند، ساخته میشوند و آیتمهای کش شده قبلی را با پارامتری با نام convertView به دست شما میرساند.
کد زیر را ببینید:
@Override public View getView(int position, View rowView, ViewGroup parent) { ViewHolder viewHolder=null; if(rowView==null) { // 1. Create inflater LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); // 2. Get rowView from inflater rowView = inflater.inflate(R.layout.row_bank_group_list, parent, false); viewHolder=new ViewHolder(); viewHolder.txtGroupName=(TextView) rowView.findViewById(R.id.text_groupName); rowView.setTag(viewHolder); } else { viewHolder=(ViewHolder)rowView.getTag(); } viewHolder.txtGroupName.setText(getItem(position).getName()); viewHolder.txtGroupName.setTypeface(new FontSystem().get_General_Font(context)); viewHolder.txtGroupName.setTextColor(context.getResources().getColor(R.color.black)); return rowView; }
کلاس داخلی ViewHolder هم یک الگو برای عدم بررسی Viewهای داخل آن است که نیازی به یافتن و تبدیل مجدد آنها نداشته باشید. در این روش شیء، داخل خصوصیت tag آیتم قرار گرفته است و وقتی از کش برداشته شود، خاصیت تگ آن را میخوانیم و مستقیما مورد استفاده قرار میدهیم. در این حالت شما بهترین استفاده را از پردازشها و حافظه، میکنید.
چهارده. یکی از کارهایی را که قبل از کار کردن در یک مسیر فیزیکی باید انجام دهید این است که مطمئن باشید اجازه نوشتن در آن ناحیه را دارید یا خیر. در غیر اینصورت برنامه شما با خطای FC روبرو میشود و اجرای آن خاتمه مییابد. به همین دلیل اکثر برنامه نویسان از متد CanWrite در کلاس File استفاده میکنند. ولی در هنگام استفاده از این متد باید دقت داشته باشید که کلاس File فقط باید حاوی مسیر باشد و اسمی از فایل مربوطه در آن نباشد. دلیل هم آن است که این احتمال میرود اگر فایلی هم وجود نداشته باشد، مقدار false را به شما برگرداند. مثال زیر قرار است فایلی را در کارت حافظه بنویسید، ولی بررسی اجازه نوشتن در مسیر، اشتباه است:
File file=new File(sdcardPath,fileName); if(file.CanWrite()) { ..... }
File file=new File(sdcardPath); if(file.CanWrite()) { file=new File(sdcardPath,filePath); ..... }
پانزده. کارت حافظه خارجی: همه برنامه نویسان اندروید حداقل یکبار از کد زیر استفاده کرده اند:
Environment.getExternalStorageDirectory()
هر برنامهای که در اندروید نصب میشود در مسیر
/Data/Data
/Data/Data/Info.Dotnettips.MyApp
/** * it will returns sd path for you * <p> * <b>Required Permission: </b>android.permission.READ_EXTERNAL_STORAGE<br/> * </p> * @return */ public List<String> GetExternalMounts() { final List<String> out = new ArrayList<>(); String reg = "(?i).*vold.*(vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*"; String s = ""; try { final Process process = new ProcessBuilder().command("mount") .redirectErrorStream(true).start(); process.waitFor(); final InputStream is = process.getInputStream(); final byte[] buffer = new byte[1024]; while (is.read(buffer) != -1) { s = s + new String(buffer); } is.close(); } catch (final Exception e) { e.printStackTrace(); } // parse output final String[] lines = s.split("\n"); for (String line : lines) { if (!line.toLowerCase(Locale.US).contains("asec")) { if (line.matches(reg)) { String[] parts = line.split(" "); for (String part : parts) { if (part.startsWith("/")) if (!part.toLowerCase(Locale.US).contains("vold")) if(new File(part).canWrite()) out.add(part); } } } } return out; }
شانزده. یکی از روشهای انتقال اطلاعات بین اکتیویتیها مختلف استفاده از Extras هاست که شما با تعیین یک نام یا کلید، اطلاعات مربوطه را ارسال و توسط همان کلید؛ اطلاعات را در اکتیویتی مقصد دریافت میکنید:
notesIntent.putExtra("PartyId", PartyId); startActivity(notesIntent);
PartyId=getIntent().getLongExtra("PartyId",0);
i.putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false); i.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, false); i.putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_FILE);
هفده. قواعد نامگذاری: برای نامگذاری متغیرها از قانون CamelCase استفاده میکنیم. ولی برای حالات زیر از روشهای دیگر استفاده میشود:
- برای ثابتها از حروف بزرگ و _ استفاده کنید.
- برای متغیرهای خصوصی از حرف m در ابتدای نام متغیر استفاده کنید.
- برای متغیرهای استاتیک از حرف s در ابتدای نام متغیر استفاده کنید.
public class MyClass { public static final int SOME_CONSTANT = 42; public int publicField; private static MyClass sSingleton; int mPackagePrivate; private int mPrivate; protected int mProtected; }
هجده: قاعده نظم و ترتیب در importها توسط مستندات گوگل بدین شکل تعریف شده است:
- نام پکیجهای ارائه شده توسط گوگل
- نام پکیجهای ثالث
- نام پکیجهای موجود در java و javax
- پکیجهای موجود در پکیج اصلی
نوزدهم. مرتب سازی متدهای دسترسی یک کلاس: بسیار خوب است که همیشه کدهای ما نظم خاصی را داشته باشد تا پیگیریهای شخصی و تیمی در آن راحتتر صورت بگیرد. برای مثال در یک کلاس ابتدا متدهای public و سپس private قرار گیرند و الی آخر.
الگوی عمومی که برای کار با جاوا صورت گرفته است به شکل زیر میباشد:
public, protected, private,abstract, static, transient, volatile, synchronized, final, native.
ادیتور intelij شامل تنظمیاتی برای مرتب سازی کدهاست که در این مورد بسیار سودمند است. با طی کردن مسیر زیر میتوانید برای آن ترتیب اینگونه موارد را مشخص کنید.
Settings>Editor>Code Style>Arrangement
در تصویر بالا متدها به ترتیب متدهای دستری بین بلوکهای کامنت method start و method end قرار گرفته اند.
همچنین شامل گزینههای دیگری نیز میباشد که به نظرم فعال کردنشان بسیار خوب است. گزینه keep overridden methods together به شما کمک میکند تا متدهایی را که رونویسی میشوند، در کنار یکدیگر قرار بگیرند که برای کلاسهای اندرویدی مثل اکتیویتیها و فرگمنتها و ... بسیار خوب است. گزینه مفید دیگر Keep dependent methods together است که در دو حالت عمقی یا خطی متدهای وابسته (متدهایی که متدهای دیگر را در آن کلاس صدا میزنند) در کنار یکدیگر قرار میدهد و مابقی گزینهها، که بسیار سودمند هست. به هر حال هر قاعدهای را که برای خود انتخاب میکنید اگر در حالت پیش فرض نیست بهتر است در مستندات پروژه ذکر شود تا افراد دیگر سریعتر به موضوع پی ببرند.
قسمت بیستم. این مورد برای افراد تازه کار میباشد که تازه اندروید استادیو را باز کردهاند و مشغول کدنویسی میباشند. یکی از مواردی که در همان مرحله اول به آن برمیخورید این است که intellisense ادیتور به بزرگی و کوچکی حروف حساس است و تنها با حرف اول سازگاری دارد. برای تغییر این مسئله باید مسیر زیر را طی کنید:
Settings>Editor>Completion>Case-sensitive Completion>None
1) مطلب شما نیاز به مقدمه دارد
نیاز به مقدمه داشتن به معنای نوشتن کلمه «مقدمه» در ابتدای یک متن نیست. به این معنا است که به خواننده بگوئید مشکل کجا بوده یا به چه دلیلی قصد دارید مطلب جاری را منتشر کنید. بنابراین جهت تهیه یک مطلب خوب، یک راست اصل مطلب را شروع نکنید. لازم است چند سطری در مورد علت انتشار آن توضیح دهید.
2) پیش از انتشار مطلب چندبار آنرا مطالعه کنید
یک مطلب خوب نیاز به جمله بندی مناسب، استفاده از نقطه، ویرگول و امثال آن دارد و بدون استفاده از آنها متن شما هرچقدر هم حرفهای باشد، خواندنش مشکل خواهد بود و جلوه مناسبی نخواهد داشت.
3) سعی کنید در عنوان مطلب خود از کلمات کلیدی استفاده کنید
استفاده از کلمات کلیدی در عنوان مطالب، جستجوی آنها را برای خواننده سادهتر کرده و همچنین کمک بزرگی است به موتورهای جستجو در یافتن نتایجی بهتر.
4) تکرار کلمات و جملات یکسان را در متن خود به حداقل برسانید
برای مثال مدام در متن خود جمله «همانطور که ملاحظه میکنید» را تکرار نکنید. استفاده از افعال تکراری و جملات تکراری در یک متن باید حداقل باشند. برای نمونه اگر جمله جاری به «میشود» ختم خواهد شد، جمله بعدی را به «میگردد» ختم کنید. اگر جملهای دارای کلمات «برای مثال» است، جمله بعدی بهتر است به همراه کلمات «برای نمونه» باشد.
5) از جملات طولانی استفاده نکنید
یک جمله باید حداکثر یک سطر یا یک سطر و نصفی طول داشته باشد و گرنه خواننده را به شدت در دنبال کردن آن به زحمت خواهید انداخت. جملات طولانی را به جملاتی کوتاهتر خرد کنید.
6) استفاده از علامت تعجب را به حداقل برسانید
اشخاصی که مدام از چندین علامت تعجب پشت سرهم استفاده میکنند یا مدام از علامت سؤال به همراه چندین علامت تعجب بهره میگیرند، حس مسخره کردن شخص مقابل و همچنین عدم تعادل روانی خود را القاء میکنند.
7) در متن خود از تصاویر استفاده کنید
انسان موجودی است بصری. قدرت یادگیری ما از طریق دیدن چند برابر زمانی است که از طریق شنیدن یا خواندن نسبت به فراگیری مطلبی اقدام میکنیم.
« ما ...
10 درصد چیزهایی را که میخوانیم
20 درصد چیزهایی را که میشنویم
30 درصد چیزهایی را که میبینیم
50 درصد چیزهایی را که میبینیم و میشنویم
70 درصد چیزهایی را که در موردشان بحث میکنیم
80 درصد چیزهایی را که تجربه میکنیم
95 درصد چیزهایی را که به دیگران میآموزیم
... یاد میگیریم
»
8) اگر در سایتی مطلب مینویسید، اهداف کلی آنرا حفظ کنید
اگر نام سایت شما برنامه نویسی است، خواننده به دنبال شعر، داستان و یا مطالب خیلی شخصی و خصوصی شما نمیگردد. سایتهای زیادی هستند که به این مقولهها میپردازند و خیلی زود سطح کاری خود را به این ترتیب به حداقل تنزل خواهید داد.
9) به صفحات داخلی سایت خود لینک دهید
در مطلب تهیه شده سعی کنید به مطالب مشابه داخلی سایت خود لینک دهید. احتمال کپی شدن مطالب شما بسیار زیاد است. به این ترتیب میتوانید خوانندهها را در لابلای متن خود به مرجع اصلی هدایت کنید.
10) دست به اختراع برچسبهای جدید، پراکنده و بیهوده نزنید
اگر گروه بندی مطالب یک سایت بر اساس برچسبها است و تاکنون برچسبهای متعددی تعریف شده است، بهتر است از همانها استفاده کنید تا اینکه دست به اختراع زده و یک برچسب کاملا جدید را ثبت کنید. برای مثال اگر مطلب شما در مورد Entity framework است و تا کنون 20 مطلب ذیل این گروه ثبت شده، اختراع برچسب جدید EF Code first نه تنها کمکی نخواهد کرد، بلکه خوانندهای را که به دنبال یافتن مطالب یک گروه خاص است، سر در گم میکند. یا اگر قصد دارید یک برچسب کاملا جدید را اضافه کنید، حتما از یک برچسب کلی موجود نیز استفاده کنید تا روابط بین مطالب حفظ شوند.
11) مطالب شما بهتر است یک قسمت نتیجه گیری نیز داشته باشد
بهتر است در پایان یک مطلب، خلاصه بحث، پیشنهادها یا حتی سؤالاتی را مطرح کنید تا بتوانید خواننده را تا حدودی وادار به عکس العمل نمائید.
12) تا حد امکان از منابع سایت خود استفاده کنید
اگر قرار است تصویری در متن قرار گیرد، اگر نیاز است فایلی در سایت مطرح شود، بهتر است این موارد در سایت جاری هاست شوند؛ تا اینکه تصویر یک سایت دیگر را مستقیما در سایت خود لینک کنیم.
13) معرفی منابع
نیازی نیست در یک سایت، همانند مقالات علمی، در انتهای مطلب لیست منابع را ذکر نمود. در اینجا میشود قسمتی از جملات را به منبع استفاده شده لینک کرد. به این ترتیب دقیقا مشخص میشود هر قسمت و هر جملهای از چه ماخذی استفاده کرده و پیگیری آن سادهتر میشود.
14) تصاویر ارائه شده را فشرده کنید
فرمت مناسب ارائه تصویر در یک سایت bmp نیست. بهترین فرمت برای سایتها png است؛ از لحاظ حفظ تعداد رنگ و همچنین کاهش حجم. به علاوه ابزارهای زیادی برای کاهش حجم فایلهای png با حداقل افت کیفیت وجود دارند.
15) در مورد کدهای خود توضیح دهید
این مورد خصوصا به سایتهای برنامه نویسی مرتبط میشود. اینکه چند سطر کد بدون توضیح را در یک مطلب قرار دادهاید، نه لطفی است و نه اهمیتی دارد! هزاران هزار سطر از این دست کدها در GitHub، CodPlex و sourceforge وجود دارند. فرق کار شما با آنها در چیست؟
باید یک قسمت «توضیحات» ذیل کدهای ارائه شده وجود داشته باشد. همان نکاتی را که حین تهیه کدها در ذهن داشتید باید بتوانید توضیح دهید و گرنه ... کار شما ارزشی نخواهد داشت.
16) مطالب تجربی شما باید قابلیت تولید مجدد داشته باشند
برای مثال امروز در حین کار به یک مطلب جدید برخوردهاید که قصد دارید آنرا به اشتراک بگذارید. ذکر این نکته جدید به تنهایی کافی نیست. باید ابتدا بتوانید ذهن خواننده را جهت رسیدن به وضعیتی که قرار داشتید، آماده کنید. اگر قصد دارید قطعه کدی را به اشتراک بگذارید، خواننده باید بتواند این قطعه از پازل را در کنار قطعات دیگری که برای او ترسیم خواهید کرد، جای دهد. یا حداقل بتواند قطعه کد شما را بدون خطا کامپایل کند.
17) یک راست به سراغ کدنویسی و اصل مطلب نروید
اگر قرار است در مورد یک فناوری جدید در طی چند جلسه بحث کنید، لازم است یک جلسه کامل در مورد «چرا به این فناوری نیاز داریم» توضیح دهید. بنابراین ذکر اینکه بدون مقدمه به سراغ کدنویسی میرویم، سؤالات بسیاری را به جا خواهند گذاشت مانند ... «مشکل روشهای قبلی چی هست؟» «مزیت این روش جدید در کجاست؟» و تا نتوانید این مسایل را شرح دهید، کار شما خریدار نخواهد داشت.
18) در زبان فارسی نیم فاصلهها را رعایت کنید
در نگارش زبان فارسی فرق است بین «آمده ام» و «آمدهام» و یا «می شود» را باید «میشود» نوشت. میشود اندکی وقت گذاشت و با مبحث نیم فاصله آشنا شد .
در کل کار کردن در یک محیط گروهی و چند نویسندهای، به مرور زمان تجربههایی را به همراه خواهند داشت که با به اشتراک گذاشتن آنها و یا طرح صریح آنها، میتوان از تکرار اشتباهات متداول جلوگیری کرد.
ابتدا مدلهای برنامه را در نظر بگیرید که از یک صورتحساب، به همراه ریز قیمتهای آیتمهای مرتبط با آن تشکیل شده است:
public class Bill { public int Id { set; get; } public string Name { set; get; } public virtual ICollection<Transaction> Transactions { set; get; } } public class Transaction { public int Id { set; get; } public DateTime AddDate { set; get; } public int Amount { set; get; } [ForeignKey("BillId")] public virtual Bill Bill { set; get; } public int BillId { set; get; } }
public class MyContext : DbContext { public DbSet<Bill> Bills { get; set; } public DbSet<Transaction> Transactions { get; set; } }
public class Configuration : DbMigrationsConfiguration<MyContext> { public Configuration() { AutomaticMigrationsEnabled = true; AutomaticMigrationDataLossAllowed = true; } protected override void Seed(MyContext context) { var bill1 = new Bill { Name = "bill-1" }; context.Bills.Add(bill1); for (int i = 0; i < 11; i++) { context.Transactions.Add(new Transaction { AddDate = DateTime.Now.AddDays(-i), Amount = 1000000000 + i, Bill = bill1 }); } base.Seed(context); } }
اولین مثال: یک جمع ساده
public static class Test { public static void RunTests() { Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, Configuration>()); using (var context = new MyContext()) { var sum = context.Transactions.Sum(x => x.Amount); Console.WriteLine(sum); } } }
خروجی SQL کوئری فوق به نحو زیر است:
SELECT [GroupBy1].[A1] AS [C1] FROM ( SELECT SUM([Extent1].[Amount]) AS [A1] FROM [dbo].[Transactions] AS [Extent1] ) AS [GroupBy1]
Arithmetic overflow error converting expression to data type int.
راه حل:
نیاز است جمع را بر روی Int64 بجای Int32 انجام دهیم:
var sum2 = context.Transactions.Sum(x => (Int64)x.Amount);
SELECT [GroupBy1].[A1] AS [C1] FROM ( SELECT SUM( CAST( [Extent1].[Amount] AS bigint)) AS [A1] FROM [dbo].[Transactions] AS [Extent1] ) AS [GroupBy1]
مثال دوم: سیستم باید بتواند با نبود رکوردها نیز صحیح کار کند
برای نمونه کوئری زیر را بر روی بازهای که سیستم عملکرد نداشته است، در نظر بگیرید:
var date = DateTime.Now.AddDays(10); var sum3 = context.Transactions .Where(x => x.AddDate > date) .Sum(x => (Int64)x.Amount);
SELECT [GroupBy1].[A1] AS [C1] FROM ( SELECT SUM( CAST( [Extent1].[Amount] AS bigint)) AS [A1] FROM [dbo].[Transactions] AS [Extent1] WHERE [Extent1].[AddDate] > @p__linq__0 ) AS [GroupBy1]
The cast to value type 'Int64' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.
var date = DateTime.Now.AddDays(10); var sum3 = context.Transactions .Where(x => x.AddDate > date) .Sum(x => (Int64?)x.Amount) ?? 0;
مثال سوم: حالتهای خاص استفاده از خواص راهبری
کوئری زیر را در نظر بگیرید:
var sum4 = context.Bills.First().Transactions.Sum(x => (Int64?)x.Amount) ?? 0;
SELECT [Extent1].[Id] AS [Id], [Extent1].[AddDate] AS [AddDate], [Extent1].[Amount] AS [Amount], [Extent1].[BillId] AS [BillId] FROM [dbo].[Transactions] AS [Extent1] WHERE [Extent1].[BillId] = @EntityKeyValue1
راه حل کنونی:
var entry = context.Bills.First(); var sum5 = context.Entry(entry).Collection(x => x.Transactions).Query().Sum(x => (Int64?)x.Amount) ?? 0;
SELECT [GroupBy1].[A1] AS [C1] FROM ( SELECT SUM( CAST( [Extent1].[Amount] AS bigint)) AS [A1] FROM [dbo].[Transactions] AS [Extent1] WHERE [Extent1].[BillId] = @EntityKeyValue1 ) AS [GroupBy1]
نکاتی که در اینجا ذکر شدند در مورد تمام توابع تجمعی مانند Sum، Count، Max و Min و غیره صادق هستند و باید به آنها نیز دقت داشت.
نکاتی در مورد ELMAH
void ErrorMailModuleName_Mailing(object sender, Elmah.ErrorMailEventArgs e) { }
<httpModules> <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" /> </httpModules>
void ErrorMail_Mailing(object sender, Elmah.ErrorMailEventArgs e) { }
void ErrorMail_Mailing(object sender, Elmah.ErrorMailEventArgs e) { if (e.Error.Exception is ApplicationException) { e.Mail.To.Add("sir1afifi@gmail.com"); } }
ذخیره Errorها در دیتابیس SQL SERVER :
<errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="..." />
<connectionStrings> <add name="conn" connectionString="Data Source=.;Initial Catalog=test;User ID=user1;Password=123456;"/> </connectionStrings>
نکاتی درمورد روشهای تبدیل (Cast) آبجکتها
با سلام
لطفا نکات، انواع روش ها، تفاوت روش ها، میزان استفاده از حافظی اصلی و ... را درمورد تبدیل نوع (cast) آبجکتها در زبان c# به یکدیگر را در طی یک مقاله ارائه نمائید.اکثر برنامه نویسان این روشها را میشناسند و مورد استفاده قرار میدهند ولی شاید روش صحیح تبدبل نوع در برنامه نویسی را به خوبی نشناسند.
با تشکر
برای انجام عملیات پرس و جوی LINQ با استفاده از روش پردازش موازی به راحتی میتوان الحاقیه AsParallel را به هر دادهای از نوع IEnumerable<T> افزود:
var data = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // پرس و جوی عادی var q1 = from i in data select i; // پرس و جو به شیوه موازی var q2 = from i in data.AsParallel() select i;
الحاقیه .AsParallel() در پرس و جویq2 نسخه موازی LINQ را بر روی متغیر data اجرا میکند و اگر همه چیز به صورت صحیح انجام شود هر دو پرس و جو باید نتایج یکسانی داشته باشند، اما نتایج عبارتند از :
//نتیجه اجرای q1 0 1 2 3 4 5 6 7 8 9 10 //نتیجه اجرای q2 0 6 1 7 2 8 3 9 4 10 5
همانطور که ملاحظه میکنید ترتیب واقعی نتایج اجرای پرس و جوها با یکدیگر متفاوتاند و نکته جالبتر آنکه با هر بار اجرای برنامه نتیجه اجرای پرس و جوی q2 با نتیجه سری قبل خودش متفاوت است که این تفاوت به چگونگی تقسیم بندی انجام کار میان هستههای سی پی یو، بستگی دارد. نکته بسیار مهم آن است که عملیات پردازش موازی خود را ملزم به حفظ ترتیب دادهها نمیداند مگر آنکه مجبورش کنیم و این رفتار پردازش موازی به دلیل بالا بردن راندمان عملیات است در نتیجه انجام پرس و جوهای موازی توسط الحاقیه .AsParallel() خیلی هم ساده نیست و ممکن است منجر به تولید نتایج ناخواسته شود.
حال اگر چگونگی ترتیب دادهها، برایمان مهم است به دو روش میتوانیم آن را انجام دهیم:
1- افزودن عبارت orderby به پرس و جو
2- استفاده از الحاقیه AsOrdered
var q3 = from i in data.AsParallel() orderby i select i; var q4 = from i in data.AsParallel().AsOrdered() select i;
که نتیجه انجام هر دو پرس و جوی بالا یکی خواهد بود. حال مسأله دیگر این است که آیا همیشه استفاده از پردازش موازی مفید خواهد بود یا خیر؟پاسخ این سؤال وابسته است به نوع مسأله و حجم داده مورد نظر و مشخصات سیستمی که قرار است از آن کد استفاده کند. چگونگی اندازه سرعت و مقدار مصرف حافظه در اجرای چهار پرس و جوی فوق در کامپیوتر من با پردازنده Intel Q9550 به شکل زیر است: