• الإعلانات

    • فيصل الحربي

      تسجيل عضوية جديدة في المنتدى   01/31/2016

      السلام عليكم ورحمة الله وبركاته  عزيزي العضو الجديد :  حاليا رسالة الإيميل لتأكيد صحة إيميلكم تذهب للبريد العشوائي ( جاري حل المشكلة )  فإذا لم تجد رسالة التحقق من إيميلكم في صندوق الوارد لديكم إتجه للبريد العشوائي ( JUNK)  وقم بتفعيل إشتراككم من هناك   

البحث في المنتدى

Showing results for tags 'value types'.

  • البحث بالتاقات

    اكتب الكلمات المفتاحيه بينها علامه الفاصله
  • البحث بكاتب الموضوع

تم إيجاد 2 نتيجة

  1. بسم الله الرحمن الرحيم في هذه المقالة سأتعرض لموضوع مهم جداً يهم المطورين المبتدئين بشكل خاص حيث عليهم أن يدركوه جيداً .. خصوصاً أن بعض أسئلة الانترفيو تكون حوله .. إنه الفرق بين Reference Types و Value Types.... في عالم الدوت نت انواع البيانات هي ثلاث أنواع : Reference Types - Value Types - Pointer Types .. معظم إستخدامنا مع البيانات هو مع النوعين الاولين اما Pointer Types فهو يستخدم نادراً.   ما الفرق بينهما؟ لديك صديق طلب منك عدد الأمس من جريدة ما .. لديك خياران: الأول أن تبعث له على الإيميل عنوان URL لموقع الجريدة على الإنترنت، و الثاني أن تذهب لتقابله في مكان ما و تعطيه نسخة من الصحيفة الورقية من الجريدة .. بالتأكيد الحل الأول أسرع و أفضل و لكن في بعض الحالات قد ألجأ للحل الثاني .. لذا علينا أن نعرف عندما نريد أن ننشأ أنواع البيانات بأنفسنا هل نجعلها Reference أم Value .   عندما تستخدم Value Type فإن CLR يقوم بحجز مكان في جزء Stack من الذاكرة و هذا المكان يحتوي على نسخة من النوع لها قيمة (نسخة ورقية من الجريدة)، أما عندما تستخدم Reference Type فإنCLR سيحجز مكان في Heap لقيمة النوع و عنوان (أو مؤشر أو مرجع) في الجزء Stack(عنوان URL لموقع الجريدة). أنظر لهذا الكود: int x = 5;ReferenceType r_type = new ReferenceType();سيتم تخزين قيمة X في Stack .. أما قيمة الكائن r_type فستخزن في Heap و سيخزن عنوان لهذه القيمة في Stack.     و هنا قد يظهر سؤال: لماذا هذا التعقيد .. لماذا لا تكن البيانات كلها من نوع واحد؟ الإجابة أن إستخدامات كلاهما تختلف .. فالأنواع Value Types تسند لها قيمة محددة واحدة مثل: int i=4;boolean log=true;أما النوع Reference Types فهو قد يحتوي على مجموعة بيانات مركبة و معقدة و من الصعب وضعها جميعاً في مكان واحد في Stack، لذا فهي تخزن في Heap و يخزن العنوان او المرجع لهذه البيانات في Stack، و الإعتماد على هذه التقنية أسرع في المعالجة لذا عندما تريد إنشاء فئة ستقوم مثلاً بإجراء عمليات معينة على قاعة بيانات أو فئة تقوم بعمل مصفوفة تستقبل بيانات من أنواع مختلفة فلابد من جعل فئتك Reference Type، أما إذا كنت تريد إنشاء فئة تعرض فقط مجموعة إختيارات  (ذكر/ أنثى) مثلا فهنا تستخدم فئة Value Type.   من الفروق الأخرى بينهما أن إنشاء فئة من نوع Reference Type يكون عن طريق كلمة class و النوع Value Type عن طريق كلمة struct: public class ReferenceType{ public int Field { get; set; } } public struct ValueType{ public int Field { get; set; }}فرق آخر بينهما، النوع Reference Type يرث من System.Object اما Value Type فهو يرث من System.ValueType التي ترث بدورها System.Object.   لمزيد من الفهم عن النوعين ننظر لهذا المثال: class Program { static void Main(string[] args) { Console.WriteLine("Reference Type:"); ReferenceType r_type1 = new ReferenceType(); ReferenceType r_type2 = new ReferenceType(); Console.WriteLine(r_type1.Equals(r_type2)); Console.WriteLine("Value Type:"); ValueType val1 = new ValueType(); ValueType val2 = new ValueType(); Console.WriteLine(val1.Equals(val2)); Console.ReadLine(); } } public class ReferenceType { } public struct ValueType { }Equals method هي وسيلة للتأكد ما إذا كان كائنين مساويين لبعض و هي ترجع true إذا كان الكائنين متساويين أو false إذا كانا غير ذلك .. قد يتبادر إلى ذهنك ان ناتج جملة Console.WriteLine الأولى سيكون true و الثانية ايضاً true، و لكن الحقيقة أن الأولى ستكون false لماذا ؟؟ لأن كلاً من r_type1 و r_type2 لهما reference مختلف في Stack، فكلاهما يشير لموضع قيم مختلفة في Heap. أما جملة Console.WriteLine الثانية فناتجها هو true لأن الوسيلة Equals هنا تقارن بين القيمتين بشكل مباشر و قيمة val1 و val2 متساويتين.   فللنظر لهذا المثال أيضاً: class Program { static void Main(string[] args) { Console.WriteLine("Reference Type:"); ReferenceType r_type1 = new ReferenceType(); ReferenceType r_type2 = r_type1; Console.WriteLine(r_type1.Equals(r_type2)); Console.WriteLine("Value Type:"); ValueType val1 = new ValueType(); ValueType val2 = val1 ; Console.WriteLine(val1.Equals(val2)); Console.ReadLine(); } }هنا سنجد ناتج الجملتين true .. لأن ReferenceType r_type2 = r_type1 معناها أن مرجع r_type2 هو نفسه مرجع r_type1، أي أن CLR قام بنسخ مرجع r_type1 و أعطاه لr_type2، إذن كلاهما يشير لنفس القيمة في Heap.   لتوضيح الفكرة السابقة نستعرض هذا المثال: class Program { static void Main(string[] args) { ReferenceType r_type1 = new ReferenceType();            ReferenceType r_type2 = r_type1;            Console.WriteLine("Before:");            Console.WriteLine(r_type1.r_field);            r_type2.r_field = 5;            Console.WriteLine("After:");            Console.WriteLine(r_type1.r_field);            Console.ReadLine(); } } public class ReferenceType { public int r_field { get; set; } }عند تنفيذ الكود سنجد ان ناتج سطر Console.Writeline الأول هو 0 و الثاني هو 5 .. لماذا؟ لأننا أخبرنا البرنامج ان مرجع r_type1 هو نفسه مرجع r_type2 و لم نكن قد أعطينا بعد أي قيمة للخاصية r_field في الكائن r_type2 .. لذا فقيمة الخاصية r_field في الكائن r_type1 هي القيمة القياسية 0، ثم أعطينا القيمة 5 لr_field  في الكائن r_type2، و لأن مرجعي الكائنين هما متساويين فهما يشيران لنفس القيمة، لذا سنجد ان مرجع r_type1 يشير للقيمة 5 أيضاً و بالتالي ستكون قيمة الخاصية r_field في r_type1 هي 5 أيضاً برغم أننا لم نعطها أي قيمة.     لنرى هل يمكن تطبيق نفس الفكرة على الأنواع ValueType: class Program { static void Main(string[] args) { Console.WriteLine("Before:"); ValueType val1 = new ValueType(); ValueType val2 = val1; Console.WriteLine(val1.v_field ); Console.WriteLine("After:"); val2.v_field = 5; Console.WriteLine(val1.v_field); Console.ReadLine(); } } public struct ValueType { public int v_field { get; set; } }هنا سنجد ان ناتج تنفيذ البرنامج هو 0 في المرتين، لأنك عندما تنشئ كائنات من النوع ValueType فإنك تنشئ نسخ من الفئة الأصلية و كل نسخة مستقلة عن الأخرى فمهما تغيرت قيمة الخاصية v_field في الكائن val2 فلن تتغير نظيرتها في الكائن val1     من الفروق الأخرى أن النوع ValueType لا يمكن الوراثة منه، اما Reference Type فيمكن ذلك.
  2. Flag Variables

    الأخوة الأعزاء فى البداية شكرا جزيلا للأخوة اللى ردوا عليا فى الموضوع السابق ورجعت بسرعة ومعايا سؤال تانى، المرة دى عن الـ Flag Variable اللى فهمتو ان من الممكن انك تغير فى بت معينة داخل متغير والمقارنة بينها وبين قيمة بت فى متغير آخر، ياترى هل هذا الشرح البسيط يمثل الهدف من الـ Flag Variable ؟ دة السؤال الأول وأثناء القراءة صادفت مثال بيتكلم عن نفس الموضوع، بس فى بعض الخطوات مش فاهمها خالص، أعتقد ان الـ سى شارب عملت نوع من الجمود على التخيل ومش قادر افكر الليونة اللى بتتعامل بيها لغة الـ C   const int CHANNEL_DOWN =    (1<<4);char    flags = 0;  /* start all flags at 0 */flags |= CHANNEL_DOWN; if ((flags & ERROR) != 0)    printf("Error flag is set\n");else    printf("No error detected\n");1: المتغير flag من نوع char كيف يساوى 0 2: كيف يتم كتابة flags |= CHANNEL_DOWN رغم اختلاف نوع المتغيرين. 3: المتغير CHANNEL_DOWN والمتغير flag مختلفين فى الحجم (int , char) كيف إذن تكون هناك عملية جمع فى كل من المتغيرين رغم اختلاف الحجم. آسف للإطالة وشكرا على الإفادة.