الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

السي شارب مقابل الجافا - نقاش علمي هادف

رائج
بدأه سلفي وأفتخر في 23 مايو 2010 · 96 رد · 13,994 مشاهدة · في الأخبار والنقاشات التقنية
مشاركة: واتساب X فيسبوك تيليجرام
#51

تفضل smile.gif

#52

أسف للتأخير أخي herch ...

أرسل اليوم رسالتي بإذن الله :)

تقبل عذري .. بارك الله فيك.

مدونة ابنتي الرضيعة: يوميات رزان

مدونتي التقنية العربية: البرمجة مع عبد المنعم

Technical Blog: Abdul Moniem's Thoughts

LinkedIn: Profile

#53

التهيئة وتعريف المتغيرات .. أو Declaring and initializing variables

في السي شارب عند تعريف Variable داخل member scope كالدوال مثلاً .. عليك تعريفه بهذه الطريقة .. نوع المتغير ثم المتغير .. وبالطبع في نهاية كل Statement الـ semi colon

int x;

ولكن احذر فإن السي شارب لن تمكنك من استخدام المتغير إذا لم تقم بتهيئته أولاً أو وضع قيمة مبدئية فيه وهذا ما دمت داخل member scope كالدوال والـ Properties ... فيجب أن يكون التعريف هكذا:

int x = 0;

أو

int x;
x=0;

طبعاً تسمح السي شارب بتعريف أكثر من متغير في نفس السطر مثل:

int x, y, z;

وإذا أردت وضع قيمة فيهم مع التعريف أو مع أحدهم فيكون:

int x, y=0,z=2;

كل الأنواع الـ intrinsic داخل السي شارب يوجد بداخلها ما يسمى default constructor والذي يمكنك من تعريف variables باستخدام الـ new keyword في السي شارب هكذا:

int x = new int();

هنا أنت تضمن أنك قمت بتعريف متغير جديد وبه قيمة مباشرة بدون تحديد ذلك وهذه القيمة هي القيمة الافتراضية للنوع .. مثلاً int يكون 0 ... أو bool يكون false

وعادة ما لا تستخدم هذه الصيغة عند تعريف الـ intrinsic types طبعاً وتستخدم الأولى لأنها أدعى للقراءة وأبسط بكثير من الثانية.

وكما ذكرنا من قبل أن كل الـ types تقم بالوراثة افتراضياً من النوع object .. وتسري هذه القاعدة أيضاً على الـ primitive types وهذه هي الشجرة الكاملة للأ data types داخل السي شارب:

post-53551-071369000 1277236076_thumb.jp

ولأن كل الـ Types تقوم بالوراثة من object فهي كلها تحتوي على بعض الصفات المشتركة والدوال المشتركة كـ ToString() و GetHashCode() ... إلخ. كما يوجد داخل كل نوع مجموعة من الـ members التي تميزه عن غيره فمثلاً int .. يوجد بداخله MaxValue و MinValue .. وهما الحد الأقصى والأدنى للمتغير int وغيرها.

وفي الدوت نت 4 تم إضافة بعض الأنواع الجديدة الرائعة .. كـ BigInteger و كـ Complex .. وهما نوعان مهمان جداً كما نعلم فالأول يستخدم للقيم العددية العملاقة. والأخر يستخدم في العمليات الحسابية ومشاكلها التي تحتوي على complex numbers للمهتمين بها طبعاً.

هناك كثير من النقاط .. ولكن سأتوقف هنا لأدع النقاش يأخذ مجراه. :)

المرفقات
1.jpg
1

مدونة ابنتي الرضيعة: يوميات رزان

مدونتي التقنية العربية: البرمجة مع عبد المنعم

Technical Blog: Abdul Moniem's Thoughts

LinkedIn: Profile

#54

في الجافا، عند تعريف حقل ما، يجب تعريفه بهذه الطريقة : نوع المتغير ثم المتغير .. وبالطبع في نهاية كل Statement الـ semi colon

int x;

ويمكن تهيئة المتغير عند تعريفه :

int x = 2;

أو بعد تعريفه:

int x;
x = 2;

عندما لا نحدد قيمة المتغير، هناك احتمالان:

-- في حالة كان حقلا في فئة ما class member، فإن ال compiler يتكفل بذلك، ويعطيه إحدى القيم التالية، حسب صنف الحقل

post-181903-011694600 1277238693_thumb.p

-- بالنسبة للمتغيرات المحلية، فالأمر مختلف، حيث يصبح إجباريا تهيئة المتغير، وإلا سنحصل على خطأ عند ال compilation.

يمكن جعل قيمة متغير ما تابثة باستعمال الكلمة المفتاحية final

final int x = 10;

الجافا تسمح بتعريف أكثر من متغير في نفس السطر مثل:

int x, y, z;

ويمكن تهيئتها عند التعريف:

int x, y = 0, z = 2;

هناك بعض القيود المفروضة على أسماء المتغيرات:

  • ألا يكون مشابها لإحدى الكلمات المفتاحية keywords الخاصة بالجافا
    post-181903-027435600 1277240639_thumb.p
    ..
  • أن لا يكون مساويا ل "true" أو "false" أو "null". الثلاثة لا تعتبر keywords !!!!
  • يحب أن تبتدأ بحرف.

بالنسبة للمسموح به، فيسمح باستعمال الأعداد، وحروف ال unicode، ولا يوجد قيد على طول الإسم.

---------------------------

كل الفئات ترث من الفئة Object، لكن ال primitive types لا ترث منها، لأنها لا تعتبر فئات. ال Wrappers مثل (Integer, Boolean, Short ...) التي تكلمت عنها سابقا تقوم بذلك، بما أنها فئات هي أيضا.

المصفوفات arrays لا تعتبر فئات، وبالتالي لا ترث من Object.

الفئة Object تحتوي على methods مثل toString و hashCode و equals ... والتي تتشاركها كل الفئات في الجافا.

بالنسبة للأعداد الكبيرة جدا ،هناك الفئتان BigInteger و BigDecimal للتعامل مع ال integers وال floating-point على التوالي؛ لكن لا وجود لفئة خاصة بال complex numbers

المرفقات
default_vals.pngkeywords.png

تم تعديل هذه المشاركة بواسطة herch في 23 يونيو 2010 في 00:26

1
#55
اقتباس
-- في حالة كان حقلا في فئة ما class member، فإن ال compiler يتكفل بذلك، ويعطيه إحدى القيم التالية، حسب صنف الحقل

السي شارب تدعم نفس الوضع.

اقتباس
يمكن جعل قيمة متغير ما تابثة باستعمال الكلمة المفتاحية final

في السي شارب يوجد نوعان من المتغيرات الثابتة ..

الأول باستخدام const keyword والثاني readonly keyword وكلاهما يستخدم قبل نوع المتغير.

الفارق بينهما كالتالي ..

في حالة const عند تهيئة متغير بقيمة معينة فلا يمكن بأي حال من الأحوال تغييرها بعد ذلك أثناء ال Compile time وإلا سيعطيك ال compiler رسالة خطأ.

أما في حالة readonly .. فيمكنك استخدامها في تهيئة المتغير في الـ runtime ثم تبقى بقية البرنامج لا يمكن أن تتغير

الاستخدام:

const int x = 10;
x = 20; // Error

أما في حالة الـ Readonly

public class Number
{

readonly int x;

public Number(int number)
{

x = 2 * number;

}
}

مدونة ابنتي الرضيعة: يوميات رزان

مدونتي التقنية العربية: البرمجة مع عبد المنعم

Technical Blog: Abdul Moniem's Thoughts

LinkedIn: Profile

#56

موضوع جميل .. بارك الله فيكم

#57
أحمد عبد المنعم كتب:

public class Number
{

readonly int x;

public Number(int number)
{

x = 2 * number;

}
}

اخي احمد حتى الان لم اعرف ما الفائدة من readonly

اي لا ارى لها اي فائدة طبعا بالتاكيد لها فائدة ولكن لاا اعرفها هل يمكنك ذكرها

In bad state

#58

الفائدة هي .. في حالة readonly .. يمكنك أن تخزن قيمة في المتغير ناتجة مثلاً من عملية حسابية تعتمد على متغير لن تستطيع الحصول على قيمته إلا في الـ runtime وفي نفس الوقت بعد حساب هذه القيمة ستبقى Constant طوال عمل البرنامج لحمايتها من التغيير بطريقة خاطئة.

أما في حالة الـ const فلا يمكنك أن تعطيها قيمة متغيرة أصلاً فهي تأخذ قيمة ثابتة فقط أي رقم مثلاً ويجب أن يكون في الـ compile time.

1

مدونة ابنتي الرضيعة: يوميات رزان

مدونتي التقنية العربية: البرمجة مع عبد المنعم

Technical Blog: Abdul Moniem's Thoughts

LinkedIn: Profile

#59

أفهم من المشاركة 53 و 54 التالي :

  • الـ primitive types في الجافا ، هي بالفعل أنواع بدائية يتم تخزينها في الـ stack .
  • في السي شارب ، لايوجد شيء اسمه primitive types ، فعندما أستخدم int أو الفئة Int32 ، فالنتيجة واحدة . أي أننا نتعامل مع كائنات ولاتوجد قيم في Stack ؟

هل هذا صحيح ؟

1

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#60
الشمري كتب:

أفهم من المشاركة 53 و 54 التالي :

  • الـ primitive types في الجافا ، هي بالفعل أنواع بدائية يتم تخزينها في الـ stack .
  • في السي شارب ، لايوجد شيء اسمه primitive types ، فعندما أستخدم int أو الفئة Int32 ، فالنتيجة واحدة . أي أننا نتعامل مع كائنات ولاتوجد قيم في Stack ؟

هل هذا صحيح ؟

في البداية كلمة primitive تعني في اللغة بدائي .. وهي كلمة تدل على الأنواع البسيطة والبدائية في أي لغة ..

في السي شارب هذه الأنواع من الممكن أن نطلقها على الـ Value types بتبسيط مخل .. المشاركة 46 أرفقت هذه الصورة:

post-53551-041332100%201276948583.jpg

وهي توضح ما هي الفئات التي من نوع Value Type .. كل هذه الأنواع ترث من فئة اسمها ValueType والتي بدورها ترث من Object في السي شارب .. وهذه الأنواع ValueType هي التي يتم تخزينها في الـ Stack .. فهي أسرع بالطبع.

أما الفئات التي من نوع Reference Type هي الأنواع التي يتم تخزينها في الـ Heap على أن يكون المؤشر الذي يؤشر عليها في الـ Stack

الصورة التالية توضح النوعين .. Value Type و Reference Type وشكلهم في الذاكرة:

post-53551-021134100%201277019707.jpg

تم تعديل هذه المشاركة بواسطة أحمد عبد المنعم في 23 يونيو 2010 في 17:21

2

مدونة ابنتي الرضيعة: يوميات رزان

مدونتي التقنية العربية: البرمجة مع عبد المنعم

Technical Blog: Abdul Moniem's Thoughts

LinkedIn: Profile

#61

بالمناسبة Int32 ليس Class ولكنه Struct أي أنه من نوع Value Type ويرمز له على سبيل الاختصار int في السي شارب.

1

مدونة ابنتي الرضيعة: يوميات رزان

مدونتي التقنية العربية: البرمجة مع عبد المنعم

Technical Blog: Abdul Moniem's Thoughts

LinkedIn: Profile

#62

في ال#C كما ذكر الأخ أحمد يمكنك تعريف Structs أو enums و في هذه الحالة يتم تخزين المتغيرات في الStack بالاضافة لجميع الأنواع الأساسية مثل int, float, double, long, short .... الخ أما في الJava لا يمكنك تعريف Structs و لهذا فكل الأنواع من تصميم المبرمج هي Class و يتم تخزينها في الHeap

1 −1

مصري في بلاد الفرنجة.

قريباً اقرأ مقالاتي على It-scoop

#63
motamayez كتب:

في ال#C كما ذكر الأخ أحمد يمكنك تعريف Structs أو enums و في هذه الحالة يتم تخزين المتغيرات في الStack بالاضافة لجميع الأنواع الأساسية مثل int, float, double, long, short .... الخ أما في الJava لا يمكنك تعريف Structs و لهذا فكل الأنواع من تصميم المبرمج هي Class و يتم تخزينها في الHeap

+1

هذه نقطة هامة جداً جداً .. وملاحظة جيدة.

إذا نظرنا إلى اللغتين الآن ..

فإن السي شارب تمكنك من بناء فئات يتم تحزينها في الـ Stack .. كـ Struct مثلاً .. فيمكنك أن تستفيد منها في الكفاءة والسرعة والحجم المحدد مسبقاً.

أما الجافا فلا يمكنك بناء فئة يتم تخزينها في الـ stack فالمتاح فقط على حسب كلام أخي herch هو الـ class على ما أتذكر .. وهو ما يتم تخزينه في الـ heap على الرغم من أنك قد لا تحتاج لأي reference type داخل أعضاء هذا ال class ولكنك مجبر على استخدامه ..

2 −1

مدونة ابنتي الرضيعة: يوميات رزان

مدونتي التقنية العربية: البرمجة مع عبد المنعم

Technical Blog: Abdul Moniem's Thoughts

LinkedIn: Profile

#64
أحمد عبد المنعم كتب:

الفائدة هي .. في حالة readonly .. يمكنك أن تخزن قيمة في المتغير ناتجة مثلاً من عملية حسابية تعتمد على متغير لن تستطيع الحصول على قيمته إلا في الـ runtime وفي نفس الوقت بعد حساب هذه القيمة ستبقى Constant طوال عمل البرنامج لحمايتها من التغيير بطريقة خاطئة.

أما في حالة الـ const فلا يمكنك أن تعطيها قيمة متغيرة أصلاً فهي تأخذ قيمة ثابتة فقط أي رقم مثلاً ويجب أن يكون في الـ compile time.

جميل جدا ربنا يجزيك كل خير

In bad state

#65
أحمد عبد المنعم كتب:

فإن السي شارب تمكنك من بناء فئات يتم تحزينها في الـ Stack .. كـ Struct مثلاً .. فيمكنك أن تستفيد منها في الكفاءة والسرعة والحجم المحدد مسبقاً.

ما الذي يعطيها الكفاءة والسرعة، هل كونها محددة الحجم مسبقا أم كونها مُخَزَّنة في ال stack؟؟

#66
اقتباس
ما الذي يعطيها الكفاءة والسرعة، هل كونها محددة الحجم مسبقا أم كونها مُخَزَّنة في ال stack؟؟

حجز شيء على الـ stack يعني incrementing the stack pointer!

عبارة عن عملية جمع سريعة جداً, و لكن الحجز على الـ Stack ليس مرن كما في حالة الـ heap, لأنك لا تستطيع عمل release إلا للـ top of stack. عملية الـ release عبارة عن عملية طرح. معظم المعالجات الحديثة(منذ السبعينيات) تأتي بتعليمات مخصصة لعمل pop و push على الـ activation record الخاصة بالدالة.

بالنسبة للـ dynamic memory سواء كانت manual أو GCed, فهذا عبارة عن نظام متكامل يحتوي على معلومات الأجزاء التي تم حجزها و الأجزاء الفارغة, ناهيك عن عملية عمليات ترتيب الذاكرة للتخلص من الـ fragmentation التي يمكن أن تحصل حسب الـ memory allocation scheme المستخدمة. ببساطة شديدة, يمكن أن تتخيل أن لديك مصفوفتان, واحدة للأماكن المحجوزة و الأخرى للأماكن الفارغة. عملية الحجز, عبارة عن عملية بحث. و عملية الـ release عبارة عن عملية نقل بين هاتين المصفوفتين. هذا تبسيط مخل, لأن العملية أكثر تعقيداً من ذلك.

تحياتي...

2 −1
#67

لا أعتقد أن هناك أي فرق من ناحية السرعة, الفرق الأساسي هو أن هذه المتغيرات لن يتم الانتظار حتى يقوم الGarbage Collector بازالتها حيث أنها تنتهي بانتهاء الScope التي تم تعريفها فيه, و سيقوم المترجم تلقائياً باعتبار المساحات التي كانت تشغلها المتغيرات المخزنة في الStack مساحات خاوية بمجرد أن ينتهي الScope التي تم تعريفها فيه. و هنا لا يحدث أن Fragmentation للذاكرة. في حين أن متغيرات الHeap يحدث لها Fragmentation و تحتاج كل فترة أن يقوم الGC بعمل Defragmentation عن طريق تحريك المتغيرات المستخدمة فوق تلك التي تم الاتسغناء عنها, و هي عملية مكلفة و لا تحدث كثيراً لأنها تحتاج لايقاف جميع الThreads في البرنامج حتى يتم الانتهاء منها, و بالطبع لن يتم تنفيذ هذه العملية الا اذا دعت الحاجة.

1

مصري في بلاد الفرنجة.

قريباً اقرأ مقالاتي على It-scoop

#68
اقتباس
أما الجافا فلا يمكنك بناء فئة يتم تخزينها في الـ stack فالمتاح فقط على حسب كلام أخي herch هو الـ class على ما أتذكر .. وهو ما يتم تخزينه في الـ heap على الرغم من أنك قد لا تحتاج لأي reference type داخل أعضاء هذا ال class ولكنك مجبر على استخدامه ..

لم أفهم ماذا تقصد ، لكن في الجافا ،

عندما يكون لدينا class يحوي على members عبارة عن primitive types ، مثل :

class A{
int x;
}

هنا x سيبقى في الـ Stack ، أليس كذلك ؟

يعني حتى لو كان " الحاوي " - الكائن ، مخزّن في الـ heap ؟

فبالتالي أين هي المشكلة ؟

logo1.png تطبيق طمأنينة ، نسخة بيتا على أندرويد

عبدالله الشمّري - Al-Shammari

CodingAlone.com

twitter @abshammeri

abshammeri AT gmail.com

github : abshammeri

#69

لا في حالة الClass سواء Java أو #C يتم حجز مكان الobject كله في الHeap و يتم وضع الReference أو الPointer على هذا الObject في الStack

تم تعديل هذه المشاركة بواسطة motamayez في 24 يونيو 2010 في 06:30

1

مصري في بلاد الفرنجة.

قريباً اقرأ مقالاتي على It-scoop

#70

أنا دماغي ساحت من موضوع ال Heap و ال stack في الجافا vs السي vs السي شارب !!

دي معلوماتي (ياريت حد يصحح):

1- في الجافا:

البيانات الأوليه (permitives) تكون في ال stack (سواء كانت local او member )

البيانات المرجعيه (references ) و من بينها arrays تكون في ال heap (سواء كانت local أو member ) و يكون هناك مؤشر عليها من ال stack.

عندما لايصبح هناك مؤشرات على بيان مرجعي, فإنه يستحق أن يزال ب GC )

2- في السي:

... أتركها لأحد رجال السي

3- السي شارب:

أتركها لأحد رجال السي شارب.

#71

في البداية .. رداً على سؤال أخي herch ..

ما الذي يعطيها الكفاءة والسرعة، هل كونها محددة الحجم مسبقا أم كونها مُخَزَّنة في ال stack؟؟

كليهما .. فالـ Stack أسرع من الـ Heap وأنا أخالف رأي أخي متميز هنا وسأتكلم عن هذه النقطة لاحقاً. ولأن المساحات التخزينية للمتغيرات معروفة مسبقاً فهي غير قابلة للزيادة أو النقصان فالتعامل معها أسرع.

قبل أن أرد على كثير من الأمور هنا التي وجدتها في النقاش .. سوف أقوم بتأصيل القضية أولاً وتوضيح الفارق بين الـ Heap والـ Stack وغالباً عندها سوف يتم الإجابة على كثير من الأسئلة والملابسات.

ما هو الـ Stack؟

الـ Stack عبارة عن مصفوفة من الأماكن داخل الذاكرة والتي يتم التعامل معها بنظام LIFO أو Last in - First out.

يتم تخزين مجموعة من البيانات داخل الـ stack وهي:

  1. قيم المتغيرات التي لها أنواع محددة - سيأتي التفصيل لاحقاً
  2. بيئة تشغيل البرنامج
  3. المتغيرات التي تمرر للدوال

وهناك حقائق هامة جداً عن الـ stack وهي:

  1. البيانات يمكن إدخالها أو حذفها فقط من العنصر الأعلى للـ Stack
  2. عملية إخراج عنصر من الـ Stack تسمى pop
  3. عملية إدخال عنصر إلى الـ stack تسمى push

الصورة التالية توضح ببساطة عمل الـ Stack وانظر التعليق عليها:

post-53551-054958000 1277395140_thumb.jp

الشكل الأيسر في الصورة السابقة يوضح عمليتي الـ pop والـ push

والشكل الأيمن في الصورة السابقة يوضح أنه عندما يتم عمل push لأي عنصر داخل الـ stack فإن المؤشر المسمى بـ Top والذي يؤشر على بداية الـ stack يتم جمع واحد عليها وهي عملية بديهية جداً في عالم الحواسب وسريعة في نفس الوقت مما يعطي الـ Stack سرعة في حجز البيانات واسترجاعها.

ما هو الـ Heap؟

الـ heap هي مكان في الذاكرة يتم تخزين البيانات فيه بحرية أكثر مما هو عليه في الـ stack فلا يوجد Data structure معين يحكم هذه العملية. لذا فمن السهل حجز البيانات واسترجاعها أو حذفها (طبعاً عن طريق الـ GC في لغات كـسي شارب وجافا) في أي وقت. ولكن هذا يكلف النظام بعض الأعمال الإضافية الدورية لصيانة هذه المساحة من الذاكرة ولاستخدام الـ GC من أجل تنظيفها وقت اللزوم. وهذا كله يكلف الـ processor دورات إضافية لا يحتاجها في الـ stack مما يضيف بعض البطيء (غير ملاحظ في العمليات والبرامج العادية طبعاً) في التعامل مع الـ heap.

post-53551-016512600 1277395430_thumb.jp

والشكل التالي يوضح كيفية عمل صيانة لهذه المساحة من الذاكرة وكيفية عمل الـ GC

post-53551-020380400 1277395523_thumb.jp

الآن نأتي للنوعين المتحدث عنهما .. الـ Value Types والـ Reference Types ...

في البداية: الـ Value Types:

هي المتغيرات التي تحتاج لوحدة واحدة فقط (أياً كانت مساحتها) لتخزينها في الذاكرة وهي الوحدة التي تحمل قيمة المتغير.

مكان تخزينها في الذاكرة ليس دائماً هو الـ Stack فهذا خطأ شائع .. ولكن الـ Value types عموماً يتم تخزينها تبعاً للمكان الذي أنشئت فيه وهذه قاعدة هامة سنعود لها بعد قليل. ولكن في الأصل إن اعتبرنا أن Value type معرف داخل دالة كـ local variable أو parameter فإنه يتم تخزينه في الـ Stack وهي أسرع كما ذكرنا ولذلك فالتعامل مع الـ Value Types أسرع من غيرها في أغلب الأحيان.

وهذه الأنواع التي يسميها الأخ herch بـ primitives وهي موجودة في كلا اللغتين السي شارب والجافا مثل الـ int و long وغيرها. وكل هذه الأنواع هي أنواع معرفة مسبقاً في اللغة سواء في الجافا أو السي شارب.

هناك نوعان إضافيان في السي شارب وهما enum والـ struct (أظن أن الـ enum في الجافا أيضاً لست متأكداً أرجو تصحيح المعلومة) وهما نوعان يقوم المبرمج باستخدامهما وقت الحاجة ومكان تخزينهما في الـ Stack ولهذا هما يمتلكان السرعة والكفاءة الناتجة من التعامل مع الـ Stack.

نأتي للـ Reference types ...

وهي أنواع تحتاج لوحدتين في الذاكرة .. الأولى في الـ Stack وهو مؤشر يحتوي على عنوان البيانات .. والثانية في الـ heap وهي تحتوي على البيانات نفسها المؤشر عليها من قبل المؤشر الموجود في الـ stack.

والـ Reference types كلها تخزن في الـ heap بنفس الطريقة التي ذكرناها الآن مقسمة على قسمين.

post-53551-033893000 1277396177_thumb.jp

يوجد حالات معينة يتم تخزين الـ reference type كله بالوحدتين المذكورتين منذ قليل (المؤشر والبيانات) في الـ heap كما سنرى بعد قليل.

فالـ Class وهو موجود في كلاً من السي شارب والجافا يخزن في الـ heap حتى وإن وجد داخله أي نوع value type. أذكركم بالقاعدة التي ذكرتها منذ قليل (الـ Value types عموماً يتم تخزينها تبعاً للمكان الذي أنشئت فيه) لذا فيتم تخزين الـ Class بكل ما فيه داخل الـ heap.

ولو تخيلنا أكثر أننا نمتلك class يوجد بداخله كلاً من النوعين value و reference فأين يتم التخزين في الذاكرة؟!

الشكل التالي يوضح .. أن الـ value type A موجود مع أبوه الـ Reference type .. أم الـ Reference type B موجود أيضاً مع أبوه .. وهذه المرة الـ pointer الخاص به داخل الـ heap وليس الـ Stack ...

post-53551-075608600 1277396427_thumb.jp

وبعد هذا التأصيل .. أعتقد أن كثير من الأسئلة والأمور تم الرد عليها ..

ولكن أحب أن أزيدكم من البيت شعراً ..

لكي نثبت بالطريقة العملية سرعة الـ Stack عن الـ heap .. دعونا نقوم ببعض الـ bench marking ...

قمت بعمل class وstruct وسأقوم بإنشاء مليون من كلاً منهما .. ونحسب الفارق في الوقت والذي سيحدد السرعة:

class RefCar
    {
        public string Brand { get; set; }
        public Pilot Pilot { get; set; }
        public string Color { get; set; }
    }

    class Pilot
    {
        public string Name { get; set; }
    }


    struct ValueCar
    {
        public string Brand { get; set; }
        public string Pilot { get; set; }
        public string Color { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch watch1 = new Stopwatch();
            watch1.Start();

            for (int i = 0; i < 1000000; i++)
            {
                RefCar car = new RefCar
                {
                    Brand = "bmw",
                    Color = "red",
                    Pilot = new Pilot
                    {
                        Name = "mohamed"
                    }
                };
            }

            watch1.Stop();
            Console.WriteLine("Ref: {0}", watch1.ElapsedMilliseconds);

            Stopwatch watch2 = new Stopwatch();
            watch2.Start();
            for (int i = 0; i < 1000000; i++)
            {
                ValueCar car = new ValueCar
                {
                    Brand = "BMW",
                    Color = "Red",
                    Pilot = "Mohamed"
                };
            }
            watch2.Stop();
            Console.WriteLine("Val: {0}", watch2.ElapsedMilliseconds);
        }
    }

والنتيجة كانت:

Ref: 69 ms

Val: 27 ms

Press any key to continue . . .

وجزاكم الله خيراً

المرفقات
1.jpg2.jpg3.jpg4.jpg5.jpg
3

مدونة ابنتي الرضيعة: يوميات رزان

مدونتي التقنية العربية: البرمجة مع عبد المنعم

Technical Blog: Abdul Moniem's Thoughts

LinkedIn: Profile

#72
هويدي كتب:

أنا دماغي ساحت من موضوع ال Heap و ال stack في الجافا vs السي vs السي شارب !!

دي معلوماتي (ياريت حد يصحح):

1- في الجافا:

البيانات الأوليه (permitives) تكون في ال stack (سواء كانت local او member )

البيانات المرجعيه (references ) و من بينها arrays تكون في ال heap (سواء كانت local أو member ) و يكون هناك مؤشر عليها من ال stack.

عندما لايصبح هناك مؤشرات على بيان مرجعي, فإنه يستحق أن يزال ب GC )

2- في السي:

... أتركها لأحد رجال السي

3- السي شارب:

أتركها لأحد رجال السي شارب.

الموضوع سهل جداً سواء في الJava أو ال#C أو ال++C يمجرد استخدامك كلمة new لتعريف object من الClass تم حجز هذا المكان بالكامل في الHeap لكل المتغيرات داخل هذا الobject سواء متغيرات primitive أو غيرها.

في ال++C يمكنك تعريف مobjects دون استخدام new و هنا يتم حجز المكان بالكامل في الStack.

2

مصري في بلاد الفرنجة.

قريباً اقرأ مقالاتي على It-scoop

#73
اقتباس

الموضوع سهل جداً سواء في الJava أو ال#C أو ال++C يمجرد استخدامك كلمة new لتعريف object من الClass تم حجز هذا المكان بالكامل في الHeap لكل المتغيرات داخل هذا الobject سواء متغيرات primitive أو غيرها.

في ال++C يمكنك تعريف مobjects دون استخدام new و هنا يتم حجز المكان بالكامل في الStack

كويس أخي ممتاز, لكن خدني على قد عقلي,,

هب أن لدينا متغير من نوع primitive هو عباره عن member(أو global ) , كيف سيتم تخزينه في ال stack , هل سيخزن قبل الدالة main ؟؟

تم تعديل هذه المشاركة بواسطة هويدي في 24 يونيو 2010 في 21:04

#74
هويدي كتب:

كويس أخي ممتاز, لكن خدني على قد عقلي,,

هب أن لدينا متغير من نوع primitive هو عباره عن member(أو global ) , كيف سيتم تخزينه في ال stack , هل سيخزن قبل الدالة main ؟؟

في هذا الرد

اقتباس
الـ Value Types:

هي المتغيرات التي تحتاج لوحدة واحدة فقط (أياً كانت مساحتها) لتخزينها في الذاكرة وهي الوحدة التي تحمل قيمة المتغير.

مكان تخزينها في الذاكرة ليس دائماً هو الـ Stack فهذا خطأ شائع .. ولكن الـ Value types عموماً يتم تخزينها تبعاً للمكان الذي أنشئت فيه

وعلى هذا:

اقتباس
لو تخيلنا أكثر أننا نمتلك class يوجد بداخله كلاً من النوعين value و reference فأين يتم التخزين في الذاكرة؟!

الشكل التالي يوضح .. أن الـ value type A موجود مع أبوه الـ Reference type .. أم الـ Reference type B موجود أيضاً مع أبوه .. وهذه المرة الـ pointer الخاص به داخل الـ heap وليس الـ Stack ...

post-53551-075608600%201277396427.jpg

الدوال لها وضع مختلف .. وكل بياناتها تخزن عند عمل البرنامج في وحدات تسمى Stack Frames وتخزن جميها في الـ Stack وانظر الشكل التالي لعمل الدوال كمثال الـ Main (في السي شارب وأظنه كذلك في الجافا للتقارب الشديد) فلو أن لدينا هذا الكود ..

class Program
{
static void MethodA( int par1, int par2)
{
Console.WriteLine("Enter MethodA: {0}, {1}", par1, par2);
MethodB(11, 18); // Call MethodB.
Console.WriteLine("Exit MethodA");
}
static void MethodB(int par1, int par2)
{
Console.WriteLine("Enter MethodB: {0}, {1}", par1, par2);
Console.WriteLine("Exit MethodB");
}
static void Main( )
{
Console.WriteLine("Enter Main");
MethodA( 15, 30); // Call MethodA.
Console.WriteLine("Exit Main");
}
}

هذا سيكون الناتج ..

Enter Main

Enter MethodA: 15, 30

Enter MethodB: 11, 18

Exit MethodB

Exit MethodA

Exit Main

وهذا الشكل يوضح شكل التنفيذ في الذاكرة والـ Stack خصوصاً طبعاً:

post-53551-078614600 1277403215_thumb.jp

جزاك الله خيراً

المرفقات
2.jpg

مدونة ابنتي الرضيعة: يوميات رزان

مدونتي التقنية العربية: البرمجة مع عبد المنعم

Technical Blog: Abdul Moniem's Thoughts

LinkedIn: Profile

#75

الدالة main ليست أول ما يتم تشغيله في البرنامج, و يوجد الكثير من الأشياء التي تحدث قبل أن تبدأ الدالة main في العمل.

مصري في بلاد الفرنجة.

قريباً اقرأ مقالاتي على It-scoop

مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…