Domanda

Mi piacerebbe test se un id non era ancora conosciuto o, se è noto, se il valore associato è cambiato. Attualmente sto usando codice simile a questo, ma è difficile da capire per chi non ha familiarità con il modello. Si può pensare a un modo per rendere più leggibile mantenendolo breve LOC?

string id;
string actual;
string stored;

if (!someDictionary.TryGetValue (id, out stored) || stored != actual) {
    // id not known yet or associated value changed.
}
È stato utile?

Soluzione

Si guarda bene a me ... recita facile come qualsiasi altra condizione di 2 if. L'unica cosa che vorrei cambiare è forse per capovolgere le negazioni per una rapida uscita:

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

Non vedo alcuna confusione a tutti, non hanno mai pensato a come un linguaggio particolarmente fastidioso, e umilmente suggerire che quelle C # sviluppatori confuso da essa si abitua ad esso. E 'comune, succinta, e dà come molti LOC al problema come merita. Trasformandolo in 10 righe di codice rende via troppo importante.

Se ho usato spesso, un qualcosa di metodo di estensione di nome come ContainsEqualValue sarebbe opportuno - ma mi piacerebbe utilizzare lo stesso codice esatto nel metodo di estensione come si deve.

Altri suggerimenti

È possibile scrivere un metodo di estensione con un buon nome:

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);
    }
}

così più tardi è possibile utilizzare

string id;
string actual;

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

Così mi sarebbe molto probabilmente disgregare e dare nomi significativi. Questo è più di leggere, ma non è necessario molto da dire nei commenti:

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) 
{

}

avvolgere ogni parte del || in proprio metodo o proprietà, che si può scrivere in questo modo

if ( IdIsNew() || IdChanged())

La dualità.

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

Non è sicuro se si tratta però più leggibile ... ma è bene sapere.

preferirei un nuovo metodo:

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;
    }
}

poi nel metodo esistente Vorrei solo:

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

Un metodo estensione sarebbe chiazza di petrolio:

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)); 
    }
}

Utilizzo:

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

Se vuoi dire che si deve fare questo più volte, ed è lungo e brutto, la logica astratta di un'altra classe e utilizzare un metodo di estensione.

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);
    }
}

Ora sostituire il codice con:

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();
}

Pur riconoscendo che il modello "prova" è necessario, non mi piace implementazioni che richiedono un parametro "out". Sembrerebbe molto più utile avere funzioni simili a TryGetValue:

  • TryGetDictValue (dizionario, chiave) restituisce null se la chiave non è nel dizionario
  • TryGetDictValue (dizionario, chiave, defaultValue) restituisce defaultValue se la chiave non è nel dizionario
  • TryGetDictValue (dizionario, chiave, valueReturningDelegate) invoca il delegato in dotazione se la chiave non è nel dizionario e restituisce il suo risultato

In ogni caso, il tipo di ritorno del risultato sarebbe quello di dati del dizionario.

E 'un peccato che non c'è modo di intrufolarsi in una macchina del tempo e fanno tali cose siano metodi di dizionario. D'altra parte, si potrebbe metterle in atto come funzioni statiche che prendono un dizionario come primo parametro.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top