2011-12-02 2 views
1

이것은 다소 이상한 질문이지만 다른 날에 나왔다. 그리고 나에게는 생각이 들었다.람다 식의 매개 변수는 언제 선호됩니까?

양식 ". (X => x.Whatever)"구절 ". (() => obj.Whatever)"에서 람다 식을 사용하는 것이 바람직 디자인이다.

다음 확장 방법을 고려하십시오.

public static class ExtensionMethods 
{ 
    public static string TryToGetTheString<T>(this T value, Func<T, string> method) 
    { 
     try 
     { 
      return method(value); 
     } 
     catch (Exception) 
     { 
      return "banana"; 
     } 
    } 

    public static string TryToGetTheStringTwo<T>(this T value, Func<string> method) 
    { 
     try 
     { 
      return method(); 
     } 
     catch (Exception) 
     { 
      return "banana"; 
     } 
    } 
} 

다음 자체 참조 클래스.

public class testClass5000 
{ 
    private int? _id; 
    public int? ID { get { return _id; } set { _id = value; } } 

    private string _urgh; 
    public string Urgh { get; set; } 

    public testClass5000 tc5k { get; set; } 
} 

다음 문자열 testClass5000에서 (Urgh가), 당신은 확장 방법 등과 같은 클래스를 구현할 수 얻기 위해 시도하는 동안, 널 (null)에 대한 검사를 피하기 위해 매우 게으른 프로세스를 사용하여,

private void main() 
    { 
     var tc = new testClass5000(); 

     textBox1.text = tc.TryToGetTheString(x => x.tc5k.tc5k.tc5k.Urgh); 

    } 

그러나 tc가 지역적으로 선언 되었기 때문에 다음과 같이 작동합니다. (x => x.tc5k.tc5k.tc5k.Urgh)이 필요한 때 (() => tc.tc5k.tc5k.tc5k.Urgh)이 바람직하다 때

private void main() 
    { 
     var tc = new testClass5000(); 

     textBox1.text = tc.TryToGetTheStringTwo(() => tc.tc5k.tc5k.tc5k.Urgh); 

    } 

나는 궁금합니다.

//////////////////////////////////////////

매개 변수를 전달하는 것이 바람직한 것으로 보이는 다음 시나리오를 생각해 냈습니다.

다음 확장 방법을 사용하십시오.

public static class ExtensionMethods 
{ 
    public static T TestOne<T>(this T value, Func<T, T> method) 
    { 
     try 
     { 
      return method(value); 
     } 
     catch (Exception) 
     { 
      return default(T); 
     } 
    } 

    public static T TestTwo<T>(this T value, Func<T> method) 
    { 
     try 
     { 
      return method(); 
     } 
     catch (Exception) 
     { 
      return default(T); 
     } 
    } 
} 

그리고 다음 코드를 사용하십시오. 이 예 .TestOne에서

private void Form1_Load(object sender, EventArgs e) 
    { 
     var firstValue = 5; 
     var secondValue = 10; 

     var resultOne = firstValue.TestOne(x => x + 1).TestOne(x => x * 2); 
     //returns 12 
     var resultTwo = secondValue.TestTwo(() => secondValue + 1).TestTwo(() => secondValue * 2); 
     //returns 20 
     var resultThree = secondValue.TestTwo(() => secondValue.TestTwo(() => secondValue + 1) * 2); 
     //returns 22 
    } 

(X => X + 1) .TestOne (X => X * 2) 중첩 식을 시작하면 필요 paremeter를 통과하지 않고 동일한 것을 달성 할 수 있기 때문에 바람직 표기법이다. 컴파일러는 이러한 목적을위한 특별 클래스를 생성하기 때문에 람다에서 직접 매개 변수 값을 주입

+0

'예외'를 ​​포착하지 마십시오! 이 모든 경우에 try/catch를 완전히 제거하고 호출 코드가 기본 반환 값을 사용하여 자동으로 문제를 숨기지 않도록합니다. – asawyer

+0

그래, 나는이 질문이 제기 된 시나리오를 만들기위한 빠른 해킹에 동의한다. – moctopus

답변

3

.

public static class Extensions 
{ 
    public static void DoSomething(this string s,Action<string> action) 
    { 
     var something = Enumerable.Range(1,100).Select(i=> String.Format("{0}_{1}",s,i)); 
     foreach (var ss in something) 
     { 
      action(ss); 
     } 
    } 
} 

그런

var something = "ABC123"; 

something.DoSomething(x=>Console.WriteLine(x)); 
//Ignoring that we could do something.DoSomething(Console.WriteLine); 

원유 예는 분명히 매개 변수없이 당신은 당신이 insterested하는 실제 값에 액세스하지 못할, 그리고 원래의 값이 개념 내에서 아무 소용이입니다.

4

은 더 비싸다.

성능 고려 사항을 제외하면 매개 변수를 삽입하는 것이 더 쓰기 쉽고 (여기서는 개인 환경 설정), 프로토 타입 (x, y) => // 작업을 매개 변수로 유지하는 것이 유용합니다 실제로 매개 변수의 값을 제공하는 것이 아닙니다. 예를 들어, Select Linq 쿼리를 사용할 때. 또는 나는 종종로드 밸런싱 시나리오 (lambda "service => service.SomeFunction()"에 사용하고, 특별한 팩토리는 서비스를 검색하고 람다를 실행한다). 매개 변수가 단순히 사용자가 제공 한 원래의 값과 동일하지 않은 경우

+0

+1 : "매개 변수의 값을 제공하는 것이 실제로 아닌 경우"라는 것이 핵심입니다. – GazTheDestroyer

+0

'x =>'버전은 변수를 포착하지 않으므로 하나의 정적 인 람다를 재사용 할 수 있습니다. '() =>'버전은 변수 캡쳐를 필요로합니다. 즉, 호출 될 때마다 새로운 람다가 생성되고 컴파일러가 다음과 같은 것을 확인해야하기 때문에'tc'에 접근 할 때마다 추가 수준의 간접 참조가 호출됩니다. if 당신의 람다는'tc = newValue'를 수행하는데, 그 새로운 값은 둘러싼 함수에서 볼 수 있습니다. 자세한 내용은 [여기] (http://blogs.msdn.com/b/oldnewthing/archive/2006/08/02/686456.aspx)를 참조하십시오. –

+0

아 멋지다. 고마워, 나는 그것을 읽을 것이다. – moctopus