2011-03-22 6 views
3

최근에 다른 메서드를 연속적으로 호출하고 적절한 값을 먼저 반환하는 방법에 따라 값을 설정하는 메서드를 작성했습니다. 내가 한 일은 한 가지 방법으로 값을 설정 한 다음 그 값을 검사하는 것이고 그다지 좋지 않으면 다음 값을 확인하는 것입니다. 여기더 우아한 방법으로 작동하는 첫 번째 방법을 반환 하시겠습니까?

private void InitContent() 
{ 
    if (!String.IsNullOrEmpty(Request.QueryString["id"])) 
    { 
     Content = GetContent(Convert.ToInt64(Request.QueryString["id"])); 
     ContentMode = ContentFrom.Query; 
    } 

    if (Content == null && DefaultId != null) 
    { 
     Content = GetContent(DefaultId); 
     ContentMode = ContentFrom.Default; 
    } 

    if (Content == null) ContentMode = ContentFrom.None; 
} 

id가 데이터베이스에없는 경우 GetContent 방법은 null를 반환해야합니다 여기에 최근의 예입니다. 이것은 간단한 예입니다. 그러나 더 많은 옵션이있는 경우 이것이 얼마나 어색해 질지 상상해보십시오. 이 작업을 수행하는 더 좋은 방법이 있습니까?

+0

왜 ContentMode가 'Content'클래스의 속성이 아닙니까? '콘텐츠'클래스의 일부로 만들면 코드가 더 짧아지고 더 읽기 쉬워 질 수 있습니다. 그리고 ContentFrom.None 열거 형이 필요하지 않습니다. NULL 콘텐츠 객체는 해당 열거 형의 논리를 대체합니다. – SolutionYogi

+0

'Content'는 제 3 자 API에서 가져온 것이기 때문에. 하나는이 프로젝트에 사용해야합니다 ... 나는 다른 제안들 중 하나처럼 그것을 포장 할 수 있다고 생각합니다. – Andy

답변

1

이 경우에는 어떤 종류의 공장 디자인 패턴을 사용해 보시기 바랍니다. 다른 제작자를 등록하여 콘텐츠 작성 절차를 추상화 할 수 있습니다. 또한 각 작성자에게 자신의 논리에 대한 환경 설정을 추가 할 수 있습니다. 게다가 다른 콘텐츠의 "ContentDefinition"클래스처럼 콘텐츠와 관련된 모든 데이터를 캡슐화하는 것이 좋습니다.

일반적으로 융통성과 효율성 사이에는 항상 상충 관계가 있음을 알아야합니다. 언젠가 당신의 첫 번째 해결책은 충분합니다 :)

9

널 통합 연산자는 원하는 의미를 가질 수 있습니다.

이다
if ((temp = W()) == null && (temp = X()) == null && (temp == Y()) == null) 
    temp = Z(); 
q = temp; 

는, Q는 W(), X(), Y()의 첫 번째 널이 아닌 경우, 또는 그들 모두가 널 (null) 인 경우 : 본질적 동일한이다

q = W() ?? X() ?? Y() ?? Z(); 

, Z()입니다.

원하는만큼 체인을 연결할 수 있습니다.

정확한 의미는 내가 스케치 한 것처럼 아닙니다. 형식 변환 규칙은 까다 롭습니다. 정확한 세부 정보가 필요한 경우 사양을 확인하십시오.

2

필자는 개인적으로 겉으로는 이질적 인 문장이 많을 때, 몇 가지 기능을 만들어야 할 때가왔다.

private ContentMode GetContentMode(){ 
} 

private Content GetContent(int id){ 
} 

private Content GetContent(HttpRequest request){ 
    return GetContent(Convert.ToInt64(request.QueryString["id"])); 
} 

private void InitContent(){ 
    ContentMode mode = GetContentMode(); 
    Content = null; 
    switch(mode){ 
    case ContentMode.Query: 
     GetContent(Request); 
     break; 
    case ContentMode.Default: 
     GetContent(DefaultId); 
     break; 
    case ContentMode.None: 
     ... handle none case... 
     break; 

    } 
} 

이렇게하면 콘텐츠 모드를 결정하는 첫 번째 단계로 나뉩니다. 그런 다음 콘텐츠를 가져옵니다.

+0

불행히도 ContentMode를 먼저 알지 못하면 ContentMode를 확인할 수 없습니다. 그렇지 않으면 아마도 이런 식으로했을 것입니다. – Andy

0
private void InitContent() 
{ 
    Int64? id = !String.IsNullOrEmpty(Request.QueryString["id"]) 
       ? Convert.ToInt64(Request.QueryString["id"]) 
       : null; 

    if (id != null && (Content = GetContent(id)) != null) 
     ContentMode = ContentFrom.Query; 
    else if(DefaultId != null && (Content = GetContent(DefaultId)) != null) 
     ContentMode = ContentFrom.Default; 
    else 
     ContentMode = ContentFrom.None; 
} 
3

당신은이의 라인을 따라, 좀 더 몰래 뭔가를 할 수 :

당신이 복잡성의 증가의 비용으로, 더 많은 소스가 있다면 도움이 될
private Int64? GetContentIdOrNull(string id) 
{ 
    return string.IsNullOrEmpty(id) ? null : (Int64?)Convert.ToInt64(id); 
} 

private Int64? GetContentIdOrNull(DefaultIdType id) 
{ 
    return id; 
} 

private void InitContent() 
{ 
    // Attempt to get content from multiple sources in order of preference 

    var contentSources = new Dictionary<ContentFrom, Func<Int64?>> { 
     { ContentFrom.Query, () => GetContentIdOrNull(Request.QueryString["id"]) }, 
     { ContentFrom.Default,() => GetContentIdOrNull(DefaultId) } 
    }; 

    foreach (var source in contentSources) { 
     var id = source.Value(); 
     if (!id.HasValue) { 
      continue; 
     } 

     Content = GetContent(id.Value); 
     ContentMode = source.Key; 

     if (Content != null) { 
      return; 
     } 
    } 

    // Default 
    ContentMode = ContentFrom.None; 
} 

.

+0

첫 번째 방법이 작동하지 않으면 다른 방법을 시도 할 필요가 없다는 점을 제외하면이 방법은 문제를 해결하지 못합니다. – Andy

+0

@Andy : 그렇습니다. 그게 전부 일종의 것입니다. 어떤 방법으로 작동하지 않을까요? – Cameron

+0

@Andy : * 오 * 샘플 코드를 완전히 잘못 읽었습니다. 죄송합니다. 내가 대답을 고쳐 줄께 ... – Cameron

1

그래, 내가 ContentFrom 모드도 실제로 원했던 걸로 알았 기 때문에, 원래의 것보다 샘플을 번역 해주었습니다. 답변


일반적으로 다음과 같은 패러다임을 사용합니다. 검색 여기에 특정 방법을 교체하고 당신은 지금 당신의 목적을 위해 v!=null 임의로 '재미'할 수있는 방법

IEnumerable<T> ValueSources() 
{ 
    yield return _value?? _alternative; 
    yield return SimpleCalculationFromCache(); 
    yield return ComplexCalculation(); 
    yield return PromptUIInputFallback("Please help by entering a value for X:"); 
} 

T EffectiveValue { get { return ValueSources().FirstOrDefault(v => v!=null); } } 

참고가 :).평가는 계산이 완료되지 않습니다 때 _value 또는 _alternative는 '재미'로 설정되어 있는지 확인합니다 방법도 게으른

참고 여기


값이 금형에 샘플을 넣어에서 내 최초의 시도이다. 실제로 많은 독립 실행 형 C# exe 파일로 컴파일되도록 배관을 어떻게 추가했는지 유의하십시오.

using System.Collections.Generic; 
using System.Linq; 
using System; 
using T=System.String; 

namespace X { public class Y 
{ 
    public static void Main(string[]args) 
    { 
     var content = Sources().FirstOrDefault(c => c); // trick: uses operator bool() 
    } 

    internal protected struct Content 
    { 
     public T Value; 
     public ContentFrom Mode; 
     // 
     public static implicit operator bool(Content specimen) { return specimen.Mode!=ContentFrom.None && null!=specimen.Value; } 
    } 

    private static IEnumerable<Content> Sources() 
    { 
     // mock 
     var Request = new { QueryString = new [] {"id"}.ToDictionary(a => a) }; 

     if (!String.IsNullOrEmpty(Request.QueryString["id"])) 
      yield return new Content { Value = GetContent(Convert.ToInt64(Request.QueryString["id"])), Mode = ContentFrom.Query }; 
     if (DefaultId != null) 
      yield return new Content { Value = GetContent((long) DefaultId), Mode = ContentFrom.Default }; 
     yield return new Content(); 
    } 

    public enum ContentFrom { None, Query, Default }; 
    internal static T GetContent(long id) { return "dummy"; } 
    internal static readonly long? DefaultId = 42; 

} } 
관련 문제