سؤال

في .NET Framework 4 بيتا 2، هناك Numerics مساحة الاسم الجديد مع struct BigInteger. و الوثائق الدول التي بل هو نوع غير قابل للتغيير، كما كنت أتوقع.

ولكن أنا بشيء من الارتباك من قبل المشغل بعد الزيادة (++). ويبدو أن هذا ديفينتيلي على التحور القيمة. ما يلي أثناء حلقة تعمل:

static BigInteger Factorial(BigInteger n)
{
    BigInteger result = BigInteger.One;
    BigInteger b = BigInteger.One;

    while (b <= n)
    {
        result = result * b;
        b++;  // immutable ?
    }
    return result;
}

وهذا ما لديها MSDN ليقوله عن المشغل الاضافة:

<اقتباس فقرة>   

ولأن الكائنات BigInteger هي   غير قابل للتغيير، ومشغل الاضافة   بإنشاء كائن BigInteger الجديد الذي   القيمة هي واحدة أكثر من BigInteger   الكائن الذي يمثله قيمة.   ولذلك، الدعوات المتكررة لزيادة   قد تكون مكلفة.

جميع جيدا والغرامة، وأود أن يفهم إذا اضطررت لاستخدام b = b++ لكن ++ على ما يبدو في حد ذاته يكفي لتغيير القيمة.

وأي أفكار؟

هل كانت مفيدة؟

المحلول

ويتم تنفيذ ++ المشغلين و-- من حيث + و- مشغلي العادية، وذلك في الواقع:

b++;

وما يعادل:

var temp = b;
b = b + 1;
<use temp for the expression where b++ was located>

والآن، وعلق، وهذا قد يبدو وكأنه يكسر ثبات، ولكن لم يحدث ذلك.

ويجب بدلا من ذلك ننظر إلى هذا الرمز كما فعل هذا:

var temp = b;
b = BigInteger.op_Add(b, 1); // constructs a new BigInteger value
<use temp ...>

وهذا سيترك الكائنين في الذاكرة، القيمة الأصلية BigInteger واحدة جديدة، المشار إليها الآن من قبل ب. يمكنك التحقق بسهولة أن هذا هو ما يحدث مع التعليمات البرمجية التالية:

var x = b;
b++;
// now inspect the contents of x and b, and you'll notice that they differ

وعلى هذا فإن الهدف الأصلي لم يتغير، وبالتالي فإنه لا يفطر ثبات، والإجابة على الجزء الجديد من هذه المسألة، وهذا ينبغي أن يكون الخيط آمنة.

وهذا هو نفس الشيء الذي يحدث لسلاسل:

String s1 = s2;
s2 += "More";
// now inspect s1 and s2, they will differ

نصائح أخرى

ومنذ BigInteger غير قابل للتغيير، ب ++ سوف يكون معادلا لمجرد أن:

BigInteger temp=b;
b=temp+1;

وبعد هذه العملية، يتم إعادة تدوير الحرارة من GC ويتم تحرير الذاكرة.

BigInteger b = BigInteger.One;

b++;  // immutable ?

في الخاص سبيل المثال ب هو متغير، الذي هو مجرد فتحة الذاكرة في إطار مكدس الأسلوب الحالي. وinitialised إلى واحد، وب ++ يأخذ ب، يخلق BigInteger الجديد (مع القيمة بمقدار) وإرجاع ذلك. المتغير ب ديها الآن حالة من BigInteger الجديدة التي تم إرجاعها.

ليكون ثبات صادقة كمفهوم هو أكثر وضوحا عند التعامل مع أنواع المراجع، لأن هناك كائن على كومة التي لا يتغير الدولة الداخلي، وذلك عندما يعود عملية / طريقة كائن جديد مع دولة مختلفة انها نوع من الواضح (على سبيل المثال يمكنك أن تفعل اشارة الاختيار المساواة بين الكائن مع object.ReferenceEquals (وجوه، وجوه).

لأنواع قيمة لا يوجد كائن على كومة، وهناك فقط فتحة في الذاكرة التي تحتوي على البتات التي هي القيمة.

حسنا، ولكن ماذا عن المشغل نفي الأحادية التي تم تعريفها على BigInteger:

public static BigInteger operator -(BigInteger value)
{
    value._sign = -value._sign;
    return value;
}

ويبدو لكسر نمط ثبات ومباشرة يتحور الكائن BigInteger. لذلك

b = -b;

والواقع يتغير وBigInteger الموجودة في المكان من دون العودة كائن جديد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top