• الإعلانات

    • فيصل الحربي

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

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

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

Showing results for tags 'reference types'.

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

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

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

  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. السلام عليكم ورحمة الله وبركاته انا مبتدأ في الاسمبلي  واحاول كتابة كود لحساب مساحة مستطيل ولكن ظهر لي هذا الخطا عند استدعاء ال procedure  Forward reference needs override  هل يمكنكم مساعدتي فيه  TITLE (square.asm) .model large .stack 4096 .386 .data msg db 0dh, 0ah, 0dh, 0ah, 'Demonisch Rectangle area calculator', 0dh, 0ah, 'Each dimension can be up to two digits long', 0dh, 0ah, '$' msgWid db 0dh, 0ah, "Width: $" msgHei db 0dh, 0ah, "Height: $" msgDim db 0dh, 0ah, "The area of the rectangle is: $" msgEnd db 0dh, 0ah, 0dh, 0ah, "Press any key to continue", 0dh, 0ah, 0dh, 0ah, "$" wid dw 0000h .code main PROC mov ax, SEG msg mov ds, ax mov ah, 9 mov dx, OFFSET msg ;Show header message int 21h getWid: mov ah, 9 mov dx, OFFSET msgWid ;Ask for width int 21h call getNum ;Call function getNum(), returns entered num in bx cmp bx, 0000h ;If an error occured getNum() returns 0, not a valid dimension so get another number je getWid mov wid, bx ;Store the width getHei: mov ah, 9 mov dx, OFFSET msgHei int 21h call getNum cmp bx, 0000h je getHei mov ax, bx ;ax stores the height mov cx, wid ;cx stores the width, which is used to know how many times to loop mov bx, 0000h ;Reset bx to 0 so it can be added to mulAns: add bx, ax ;Keep adding the height to itself dec cx cmp cx, 0000h ;Until width is 0 jg mulAns disAns: mov ah, 9 mov dx, OFFSET msgDim int 21h call disNum proEnd: mov ah,9 mov dx,OFFSET msgEnd int 21h mov ah, 1 ;Wait for any key, allows the user to read any output int 21h ;before the programme ends and the window closes mov ah, 4ch int 21h main ENDP getNum PROC near .data msgBN db " [Only enter digits]$" msgZ db " [Zero number not allowed]$" numIn dw 0000h .code push ax ;This sub requires bx to pass the number back push cx ;But everything else can be reserved push dx push si push di readNumS: ;Start mov cx, 0000h mov numIn, 0000h ;Reset the values, otherwise repeated calls to this function will use the last stored values readNumG: ;Get mov ah, 8 ;Silent read mode, does not echo to the screen int 21h mov bx, 0000h mov bl, al cmp bl, 0Dh ;Return je readNumF cmp bl, 30h ;0 (ASCII 48) jl badNum cmp bl, 39h ;9 (ASCII 57) jg badNum mov ah, 6 ;Char display mode mov dl, bl int 21h ;Display the entered char sub bl, 30h ;Turn into digit mov dx, numIn mov ax, dx mov ch, 00h readNumL: ;Loop ten times, moving all the digits in the current numIn 1 place forward (effectively * 10) add ax, dx inc ch cmp ch, 09h jl readNumL add ax, bx mov numIn, ax inc cl cmp cl, 02h ;Only allow 2 digit numbers jl readNumG readNumF: cmp numIn, 0000h ;Do not accept the number 0 je zeroNum mov bx, numIn readNumE: pop di ;Returns all of the registers apart from bx to there original states pop si pop dx pop cx pop ax ret ;Errors zeroNum: mov ah, 9 mov dx, OFFSET msgZ int 21h mov bx, 0000h jmp readNumE badNum: ;Digit was expected but not entered mov ah, 6 ;Display the offending character mov dl, al int 21h mov ah, 9 mov dx, OFFSET msgBN int 21h mov bx, 0000h jmp readNumE getNum ENDP ;--------------------------------------------------------------------------------; disNum PROC .data numOut dw 0000h .code mov numOut, bx ;Store a copy before pushing, so the original after this method stays the same push ax push bx push cx push dx push si push di mov bx, numOut ;Use this copy disNumF: mov cl, 00h cmp bx, 03E8h ; 1000 jge getThou cmp bx, 0064h ; 100 jge getHun cmp bx, 000Ah ; 10 jge getTen jmp disUnit getThou: inc cl sub bx, 3E8h cmp bx, 3E8h jge getThou disThou: add cl, 30h mov ah, 6 mov dl, cl int 21h mov dl, 2Ch ;Display thousand comma int 21h mov cl, 00h cmp bx, 64h jl disHun getHun: inc cl sub bx, 64h cmp bx, 64h jge getHun disHun: add cl, 30h mov ah, 6 mov dl, cl int 21h mov cl, 00h cmp bx, 0Ah jl disTen getTen: inc cl sub bx, 0Ah cmp bx, 0Ah jge getTen disTen: add cl, 30h mov ah, 6 mov dl, cl int 21h mov cl, 00h cmp bx, 01h jl disUnit disUnit: add bl, 30h mov ah, 6 mov dl, bl int 21h pop di ;Restore previous values, most importantly bx in case the user wants to use that number again pop si pop dx pop cx pop bx pop ax ret disNum ENDP ;--------------------------------------------------------------------------------; END mainfinal.asm
  3. 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) كيف إذن تكون هناك عملية جمع فى كل من المتغيرين رغم اختلاف الحجم. آسف للإطالة وشكرا على الإفادة.