2010-06-10 1 views
6

ID가 아직 알려지지 않았는지 테스트하고 싶거나 알려진 값이 있으면 연결된 값이 변경되었는지 테스트하고 싶습니다. 나는 현재 이와 비슷한 코드를 사용하고 있지만 패턴에 익숙하지 않은 사람들은 이해하기 어렵다. LOC에서 짧게 유지하면서 더 읽기 쉽게 만드는 방법을 생각해 볼 수 있습니까?이 사전 TryGetValue 코드를 더 읽기 쉽게하려면 어떻게해야합니까?

string id; 
string actual; 
string stored; 

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

답변

1

그것은 나에게 잘 보인다는 ... 다른 두 조건 문처럼 쉽게 읽습니다. 나는 아마도 변경하려는 유일한 것은 조기 종료에 대한 부정을 뒤집을 수 있습니다 : 나는 특히 귀찮은 관용구로 생각하지 못했던, 전혀에서 혼란이 표시되지 않는

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

및 겸손하게 그걸로 혼란스럽게 C#을 devs 제안 익숙해 지. 그것은 공통적으로, 숙신이며, 많은 LOC를 문제만큼 가치있게 제공합니다. 그것을 10 줄의 코드로 바꾸면 이 너무 중요합니다.

자주 사용하는 경우 ContainsEqualValue과 같은 이름의 확장 메서드를 사용하는 것이 적절합니다. 그러나 확장 메서드에서 사용하는 것과 똑같은 코드를 사용하고 싶습니다.

+2

'out'매개 변수의 사전 선언이 필요한 경우 2 조건문과 완전히 동일하지 않습니다. "…그것에 익숙해?" devs는 "혼란 스럽다", * per se *는 아닙니다. 왼쪽에서 오른쪽으로 읽는 베테랑 프로그래머조차도이 글을 읽으려고 앞뒤로 튀어 오르며 그렇게하면서 마음 속의 몇 가지 요소를 뒤적 거리며 조종해야합니다. 이것은 어려운 일이 아니지만 자연스럽지 않습니다. 이것은 다소 절차적인 코드이며 반복 및 오류의 기회를 제공합니다. 가독성은 합법적 인 관심사이며 'bool'결과가 의미 상 약한 'TryGetValue'입니다. – Jay

+0

@ Jay : 왜 out 변수의 선언을 확인하겠습니까? 그것은 명백하게 (또는 컴파일러가 불평 할 것입니다) 분명히 값이 무엇인지 이전에 신경 쓰지 않아야합니다 (out 파라미터이므로 값은 함수에 의해 사용되지 않습니다). 이것은 조건부 대신에 '아웃'에 관한 것입니까? 이 진술서에서 인정할 수있는 유일한 점은 1.) 부작용이 조건부에 있고, 2.) 조건부가 순서에 의존한다는 것입니다. 'bool Try * (out)'은 BCL의 잘 짜여진 관용구로 devm이 grok을 기대하기 때문에 첫 번째 것을 용서합니다. –

+0

@ 제이 : 귀하의 의견은 "spot-on"입니다. 필자의 의견으로는 답을 읽는 것이 가독성을 언급하지 못합니다. 이것이 내가 제안한 코드를 구성한 이유입니다. – AMissico

4

그래서 나는 아마도 그것을 해독하고 의미있는 이름을 부여 할 것입니다. 이 읽기 더 많은,하지만 당신은 의견 말을 많이 필요하지 않습니다 :

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

} 
+0

연산자 우선 순위 규칙과 함께 'out' 키워드가 초기화됩니다. – mafu

+0

TryGetValue가 초기화하기 위해 out 매개 변수가 함수 내에 설정되어야합니다. –

+1

'stored'는'TryGetValue'를 호출 한 후에 항상 초기화됩니다. 그것은 'out'매개 변수의 규칙입니다. 분명히 그것은 유효한 값이 아닙니다. – leppie

2

이중성을.

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

더 읽기 쉽지만 잘 모르겠지만 ... 알아두면 좋을 것 같습니다.

+2

원본보다 읽기가 어렵다고 생각합니다. – mafu

+0

-1은 읽을 수 없습니다. 나는이 말을 이해하고 고치는 데 어려움을 겪을 것이다. 특히'stored'가'out'이기 때문에 같은 문장에서 사용합니다. 당신은 내가 무슨 일이 일어나고 있는지 이해하기 위해 각 요소를 읽도록 강요하고 있습니다. – AMissico

+0

@AMissico : 절차 코드의 함정 : – leppie

3

각 부분을 || 자신의 메서드 나 속성에, 당신은 내가 새로운 방법을 선호하는 것이

if (IdIsNew() || IdChanged()) 
+0

많은 줄의 코드를 작성하지 않는 것이 좋습니다. – mafu

+2

잠재적 인 오류를 제거하지 않으면 새로운 방법을 만들지 않습니다. 가독성과 유지 보수가 향상되면 새로운 방법을 만들겠습니다. – AMissico

1

처럼 쓸 수있는 것보다 : 기존의 방법에 다음

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

'AddValue'는 실제로 아무 것도 수행/변형시키지 않는 끔찍한 이름입니다. 'CanAddValue'가 더 나은 이름 일 수 있습니다. – leppie

+0

좋은 생각. 어쩌면 오히려 사전 확장 방법일까요? 명명은 아직 이상합니다. – mafu

+0

명명 된 이름이 이상했다. 그것을 바꿨다.그리고 네, 사전에 확장 메서드로 구현할 수 있습니다. 아마도 조금 더 좋을 것입니다 ... –

5

당신은 좋은 이름으로 확장 방법을 쓸 수 있습니다 :

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. 
} 
+1

+1. "out"매개 변수가 싫고 일반적으로 TryGetValue에 대한 액세스를 확장 메서드로 랩핑합니다 (예 : TryGetValueOrDefault를 사용하여 항목을 직접 반환하거나 null을 입력하거나 항목을 찾을 수없는 경우 0). –

+0

"out"= 코드가 명확하지 않습니다. – AMissico

0

연장 방법을 사용할 수 있습니다 :

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") 
0

당신이 반복적으로이 작업을 수행해야한다는 것을 의미하는 경우, 그리고 길고 추한, 논리를 다른 클래스로 추상화하고 확장 메소드를 사용하십시오.

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. 
} 
+2

코드가 너무 많습니다. 너무 단순하기 때문에 너무 복잡합니다. – AMissico

+0

@AMissico "너무 많은 코드"는 주관적입니다. 도메인 및 사용 요구에 따라 다릅니다. 이것은 단지 사용법의 가독성을 선호하는 하나의 접근 방식으로 제공되며, 이것이 여러 곳에서 이루어져야 만하는 수표 인 경우에만 의미가 있습니다. 매개 변수의 수가 증가하면 가독성이 떨어집니다. 그렇게함으로써 가치를 볼 수 있다면,이 저하를 완화 할 수있는 방법입니다. – Jay

+0

나는 당신과 완전한 계약을 맺고 있습니다. 그래서 나는 투표하지 않았습니다. 나는 10 가지 코드 라인을 추가하고 더 읽기 쉽게 만들지 않았으며 혼란스런 진술을 변경하지 않았기 때문에 당신의 접근 방식이 조금 무거워 보일 수 있도록 "희박"했다. – AMissico

0
public T GetValue(int id, object actual) 
{ 
    object stored; 
if (someDictionary.TryGetValue (id, out stored) || stored == actual) 
    return stored; 
    return new object(); 
} 
0

"try"패턴이 필요하다는 것을 알고 있지만 "out"매개 변수가 필요한 구현은 싫습니다. 그것은 훨씬 더 유용 TryGetValue 유사한 기능을 보일 수있을 것입니다 : 키가 사전에없는 경우

  • TryGetDictValue (사전, 키) null을 반환
  • TryGetDictValue 키가 아닌 경우 (사전, 키, DEFAULTVALUE가) DEFAULTVALUE을 반환 사전
  • 키가 사전에없는 모든 경우의 결과

을 반환하는 경우 TryGetDictValue이 (사전, 키, valueReturningDelegate)가 공급 대리자를 호출, 결과의 반환 형식이 사전 데이터의 그 것이다.

타임 머신에 몰래 들어가서 그런 것들을 사전의 방법으로 만드는 것은 너무 어렵습니다. 다른 한편으로, 정적 함수로서 사전을 첫 번째 매개 변수로 사용하여이를 구현할 수 있습니다.

+0

이것은 여전히 ​​확장 메서드로 수행 할 수 있습니다. 마지막 메서드를 사용했을 때의 의미입니다. – Dykam