ماذا عن قابلة للتغيير البنية التي هو غير قابل للتغيير من وجهة نظر الخارجية الرمز ؟

StackOverflow https://stackoverflow.com/questions/3807030

سؤال

التحديث:أنها وقعت لي بعد نشر هذا السؤال أن الجانب السلبي الرئيسي لهذه الفكرة ببساطة أن مثل هذا النوع سوف تكون سهلة الاستخدام بشكل غير صحيح.هذا هو نوع يجب أن تستخدم بطريقة محددة جدا لرسم أي فوائد.ما كان في الأصل في العقل شيء من شأنه أن يكون استخدام مثل هذا (الخلاف مع SquareRootStruct على سبيل المثال من السؤال الأصلي فقط من أجل التناسق):

class SomeClass
{
    SquareRootStruct _key;

    public SomeClass(int value)
    {
        _key = new SquareRootStruct(value);
    }

    public double SquareRoot
    {
        // External code would have to access THIS property for caching
        // to provide any benefit.
        get { return _key.SquareRoot; }
    }

    public SquareRootStruct GetCopyOfKey()
    {
        // If _key has cached its calculation, then its copy will carry
        // the cached results with it.
        return _key;
    }
}

// elsewhere in the code...
var myObject = new SomeClass();

// If I do THIS, only a COPY of myObject's struct is caching a calculation,
// which buys me nothing.
double x = myObject.GetCopyOfKey().SquareRoot;

// So I would need to do this in order to get the benefit (which is,
// admittedly, confusing)...
double y = myObject.SquareRoot;

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


لنفترض لدي struct أن كنت تريد أن يكون لها الخصائص التالية:

  1. ثابتة من الخارجية وجهة نظر
  2. سريع إلى تهيئة
  3. كسول حساب (المؤقت) من خصائص معينة

ومن الواضح أن السمة الثالثة يعني التحولية, التي نعلم جميعا هو سيء (على افتراض شعار "لا تجعل قابلة للتغيير أنواع قيمة!" تم حفرها في رؤوسنا بما فيه الكفاية).ولكن يبدو لي أن هذا من شأنه أن يكون مقبولا طالما قابلة للتغيير جزء مرئيا فقط داخليا إلى النوع نفسه من خارج رمز منظور قيمة أن يكون دائما هو نفسه.

هنا مثال على ما أتحدث عنه:

struct SquareRootStruct : IEquatable<SquareRootStruct>
{
    readonly int m_value;  // This will never change.

    double m_sqrt;         // This will be calculated on the first property
                           // access, and thereafter never change (so it will
                           // appear immutable to external code).

    bool m_sqrtCalculated; // This flag will never be visible
                           // to external code.

    public SquareRootStruct(int value) : this()
    {
        m_value = value;
    }

    public int Value
    {
        get { return m_value; }
    }

    public double SquareRoot
    {
        if (!m_sqrtCalculated)
        {
            m_sqrt = Math.Sqrt((double)m_value);
            m_sqrtCalculated = true;
        }

        return m_sqrt;
    }

    public bool Equals(SquareRootStruct other)
    {
        return m_value == other.m_value;
    }

    public override bool Equals(object obj)
    {
        return obj is SquareRootStruct && Equals((SquareRootStruct)obj);
    }

    public override int GetHashCode()
    {
        return m_value;
    }
}

الآن, من الواضح أن هذا هو المثال تافهة, ، Math.Sqrt يكاد يكون من المؤكد ليس مكلفا بما فيه الكفاية للنظر في هذا النهج من المفيد في هذه الحالة.إنه مثال فقط لأغراض التوضيح.

ولكن تفكيري هو أن هذا يحقق لي ثلاثة أهداف حيث الأكثر وضوحا النهج البديلة لن.على وجه التحديد:

  • أنا يمكن أن أداء الحساب في نوع منشئ ؛ ولكن هذا من شأنه أن تقصر 2 الهدف أعلاه (سريع إلى تهيئة).
  • أنا يمكن أن أداء الحساب على كل الممتلكات ؛ ولكن هذا من شأنه أن تقصر من 3 الهدف أعلاه (التخزين المؤقت حساب النتيجة في المستقبل بالوصول).

لذا نعم, هذه الفكرة بشكل فعال من شأنه أن يؤدي إلى نوع القيمة التي يتم داخليا قابلة للتغيير.ومع ذلك ، بقدر الخارجية أي رمز يمكن أن نقول (كما أرى) ، تظهر غير قابل للتغيير ، في حين حاملا معه بعض مزايا الأداء (مرة أخرى ، أدرك المثال أعلاه أن لا يكون من المناسب استخدام هذه الفكرة ؛ "الأداء الفوائد" أنا أتحدث عن أن تكون الوحدة على حساب يجري في الواقع مكلفة بما فيه الكفاية لتبرير التخزين المؤقت).

أنا في عداد المفقودين شيء ، أو أن هذا في الواقع جديرة بالاهتمام الفكرة ؟

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

المحلول

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

نصائح أخرى

ما تصفون ربما يمكن أن تعمل إلى حد ما ، ولكن مع تحذير هام:نتيجة بطء الحساب قد أو قد لا تحصل على تخزين عندما يتم حسابها.على سبيل المثال ، إذا كان الحساب يتم على البنيات عاد قبل التعداد ، فإن النتائج سوف يحصل المخزنة في "المؤقتة" البنيات و سيتم التخلص منها بدلا من نشر مرة أخرى في تلك المخزنة في بنية البيانات.

هذا يشبه المستقبل.كان هناك ذكر بعض من أفضل دعم العقود الآجلة في C# 4.0 موازية امتداد.(مثل الحوسبة لهم على آخر core/موضوع بالتوازي مع العمل العادي الخاص بك).

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