كيف يمكنني جعل رمز TrygetValue القاموس هذا أكثر قابلية للقراءة؟

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

سؤال

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

string id;
string actual;
string stored;

if (!someDictionary.TryGetValue (id, out stored) || stored != actual) {
    // id not known yet or associated value changed.
}
هل كانت مفيدة؟

المحلول

يبدو الأمر جيدًا بالنسبة لي ... يقرأ سهلاً مثل أي شرطين آخران إذا كان بيان. حول الشيء الوحيد الذي قد أغيره هو قلب النفي للخروج المبكر:

if (someDictionary.TryGetValue(id, out stored) && stored == actual) {
    return;
}
// store new value

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

إذا استخدمته كثيرًا ، فإن طريقة التمديد تدعى شيئًا مثل ContainsEqualValue سيكون مناسبة - لكنني سأستخدم نفس الرمز بالضبط في طريقة التمديد كما لديك.

نصائح أخرى

يمكنك كتابة طريقة تمديد باسم جيد:

public static class Utility
{
    public static bool ValueChangedOrUnknown(this Dictionary<string, string> dictionary, string id, string actual)
    {
        string stored = null;
        return (!dictionary.TryGetValue(id, out actual) || stored != actual);
    }
}

لذا في وقت لاحق يمكنك استخدام

string id;
string actual;

if (someDictionary.ValueChangedOrUnknown(id, actual) {
    // id not known yet or associated value changed.
}

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

bool isKnown = someDictionary.TryGetValue (id, out stored);
// can only change when it is known
bool valueChanged = isKnown && stored != actual;

// quite self-explanatory, isn't it?
if (!isKnown || valueChanged) 
{

}

لف كل جزء من || في طريقتها أو خاصتها الخاصة ، مما يمكنك كتابته مثل هذا

if ( IdIsNew() || IdChanged())

الازدواجية.

if (!(someDictionary.TryGetValue (id, out stored) && stored == actual)) ...

لست متأكدًا مما إذا كان الأمر أكثر قابلية للقراءة ... لكن من الجيد معرفة ذلك.

أفضل طريقة جديدة:

public bool ShouldSetValue(Dictionary someDictionary, object id,object actualValue)
{
    string stored;

    if (someDictionary.TryGetValue (id, out stored)) 
    {
        if (stored != actualValue)
            return true;
    }
    else
    {
        return true;
    }
}

ثم في الطريقة الحالية فقط:

if (ShouldSetValue(someDictionary,id,actual))
{
     someDictionary[id]=actual;
}

طريقة التمديد ستكون بقعة:

public static class DictionaryExtensions
{
    public static bool ShouldAddValue<TKey, TValue>(this Dictionary<TKey, TValue> someDictionary, TKey id, TValue actual)
    {
        TValue stored;
        return (!someDictionary.TryGetValue(id, out stored) || !stored.Equals(actual)); 
    }
}

الاستخدام:

someDictionary.ShouldAddValue("foo", "bar")

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

public static class DictionaryExtensions
{
    public static DictionaryChecker<TKey,TValue> contains<TKey,TValue>(this IDictionary<TKey,TValue> dictionary, TValue value)
    {
        return new DictionaryChecker<TKey,TValue>(value, dictionary);
    }
}

public class DictionaryChecker<TKey,TValue>
{
    TValue value;
    IDictionary<TKey,TValue> dictionary;

    internal DictionaryChecker(TValue value, IDictionary<TKey, TValue> dictionary)
    {
        this.value = value;
        this.dictionary = dictionary;
    }

    public bool For(TKey key)
    {
        TValue result;
        return dictionary.TryGetValue(key, out result) && result.Equals(value);
    }
}

الآن استبدل الرمز الخاص بك بـ:

if(!someDictionary.contains(actual).For(id)){
    // id not known yet or associated value changed.
}
public T GetValue(int id, object actual)
{
  object stored;
 if (someDictionary.TryGetValue (id, out stored) || stored == actual) 
    return stored;
  return new object();
}

على الرغم من أنني أدرك أن نمط "المحاولة" ضروري ، إلا أنني لا أحب التطبيقات التي تتطلب معلمة "خارج". قد يبدو الأمر أكثر فائدة للغاية لها وظائف مماثلة لـ TrygetValue:

  • TrygetDictValue (القاموس ، المفتاح) يرجع فارغة إذا لم يكن المفتاح في القاموس
  • TrygetDictValue (القاموس ، المفتاح ، DefaultValue) إرجاع DefaultValue إذا لم يكن المفتاح في القاموس
  • TrygetDictValue (القاموس ، المفتاح ، ValuereturningDelegate) يستدعي المندوب المقدم إذا لم يكن المفتاح في القاموس ويعيد نتيجته

في كل حالة ، سيكون نوع الإرجاع للنتيجة هو نتيجة بيانات القاموس.

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

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