수동으로 델리게이트 만들기 vs Action / Func 델리게이트 사용
오늘 나는 선언하는 것에 대해 생각하고 있었다.
private delegate double ChangeListAction(string param1, int number);
그러나 사용하지 않는 이유 :
private Func<string, int, double> ChangeListAction;
또는 ChangeListAction
반환 값이 다음을 사용할 수 있습니다.
private Action<string,int> ChangeListAction;
선언 delegate
키워드 로 대리 선언 할 때 장점은 무엇입니까?
.NET 1.1 때문 입니까? .NET 2.0 Action<T>
과 함께 .NET 3.5와 함께 왔 Func<T>
입니까?
장점은 명확합니다. 유형에 명시적인 이름을 지정하면 해당 유형이 수행하는 작업이 더 명확 해집니다.
코드를 때도 도움이됩니다. 다음과 같은 오류 :
cannot convert from Func<string, int, double> to Func<string, int, int, double>
다음과 같이 말하는 것보다 덜 도움이됩니다.
cannot convert from CreateListAction to UpdateListAction
또한 두 가지 작업을 수행하는 경우 컴파일러가 실수로 다른 대리를 수행하는 경우에는 사용하지 않도록 보장 할 수 있습니다.
대리자 사용 의 출현 Action
과 Func
가족은 사용자 지정 대리 유효성 덜 사용하게 만들었지 만 후자는 여전히을 찾습니다. 사용자 지정 대리자의 장점은 다음과 같다.
다른 사람들이 지적했음을 일반
Action
과 는 달리 의도를 명확하게 전달합니다Func
( Patrik 은 의미있는 매개 변수 이름에 대해 매우 좋은 지적을합니다).다른 두 개의 일반 대리자와 달리
ref
/out
매개 변수 를 사용할 수 있습니다 . 예를 들어, 당신은 수 있습니다.public delegate double ChangeListAction(out string p1, ref int p2);
하지만
Func<out string, ref int, double> ChangeListAction;
또한 사용자 지정 델리게이트를 사용하면
ChangeListAction
코드베이스 어딘가에 한 번만 작성하면 (정의를 의미합니다). 반면에 정의하지 않는Func<string, int, double>
모든 곳에 흩어져 있어야합니다 . 후자의 경우 서명을 변경하는 것은 번거 롭습니다. 건조하지 않은 나쁜 경우입니다.유행하는 매개 변수를 사용합니다.
public delegate double ChangeListAction(string p1 = "haha", int p2);
하지만
Func<string, int, double> ChangeListAction = (p1 = "haha", p2) => (double)p2;
params
메소드의 매개 변수에 대한 키워드를 누르십시오Action/Func
.public delegate double ChangeListAction(int p1, params string[] p2);
하지만
Func<int, params string[], double> ChangeListAction;
글쎄, 당신이 선호하지 않고 16 개 이상의 변수가 필요하다면 (현재) :)
Action
및의 장점 Func
:
빠르고 더러워서 다 사용합니다. 사용 사례가 사소한 경우 코드가 짧아집니다 (사용자 지정 대리자가 나와 함께 유행하지).
더 중요한 것은 도메인간에 호환되는 유형입니다.
Action
그리고 프레임Func
워크는 정의, 그들은 한 언어 변수 유형이 일치하게 작동합니다. 당신은 할 수 없습니다ChangeSomeAction
에 대한ChangeListAction
.Linq
이 공간을 잘 활용합니다.
대리 선언 적으로 선언하면 일부 유형 검사에 도움이 될 수 있습니다. 컴파일러는 변수에 할당 된 대리자가 서명과 호환되는 임의의 작업이 아닌 ChangeListAction으로 사용할 수 있습니다.
그러나 자신의 대리라는 확실한 가치는 론적 의미를 부여한다는 의미입니다. 코드를 읽는 사람은 델리게이트가 이름으로 무엇을하는지 알 수 있습니다. 세 개의 int 필드가있는 클래스가 대신 세 개의 int 요소의 배열을 선언 할 상상해. 배열은 동일한 작업을 수행 할 수 있습니다. 이름은 개발자에게 유용한 의미 정보를 제공합니다.
LINQ와 같은 범용 라이브러리를 디자인 할 수 있고 Func, Predicate 및 Action 대리 매합니다. 이 경우 대리자는 실행 및 조치를하거나 술어로 사용하고 있고, 게다가 사전 정의 된 의미를 갖지.
참고로 Tuple 대 자체 클래스 자체 클래스 선택 가능합니다. 모든 것을 튜플에 붙일 수있는 속성은 유형 사용에 아무것도 알려주지 않는 항목입니다. Item1, Item2입니다.
일부 답변에서 승리가 명확하게 언급했듯이 유형의 이름을 지정합니다 API 사용자가 이해하기가 더 많았습니다. 대부분의 경우 공개 API에 대한 대리자 유형을 선언하지만 Func<?,?>
내부적으로 사용하는 것은 괜찮습니다 .
다른 답변에서 언급되지 않은 대리자 유형을 선언하는 큰 이점 중 하나는 유형에 이름을 지정하는 것 외에 유용성이 크게 증가하는 것입니다.
대표 만 사용할 수있는 특별한 사용 사례를 찾았습니다.
public delegate bool WndEnumProc(IntPtr hwnd, IntPtr lParam);
[DllImport("User32.dll")]
public static extern bool EnumWindows(WndEnumProc lpEnumFunc, IntPtr lParam);
기능 / 동작 사용은 작동하지 않습니다. 'Namespace.Class.WndEnumProc' is a 'field' but is used like a 'type'
:
public Func<IntPtr, IntPtr, bool> WndEnumProc;
[DllImport("User32.dll")]
public static extern bool EnumWindows(WndEnumProc lpEnumFunc, IntPtr lParam);
다음 코드는 예외가 발생하는 System.Runtime.InteropServices.DllImportAttribute
유형의 마샬링을 지원하지 않습니다 .
[DllImport("User32.dll")]
public static extern bool EnumWindows(Func<IntPtr, IntPtr, bool> lpEnumFunc, IntPtr lParam);
나는 모든 사람에게 보여 주기이 예를 제시한다. 그리고 귀하의 질문에 대한 응답입니다why not use Action<T>/Func<T> ?
Func / Action에서 너무 많은 변수를 가져 오기 시작하면 대리 튼 명시 적으로 선언하십시오. "두 번째 정수가 다시 무엇을 의미하는지 의미합니까?"계속해서 무엇을보아야합니다.
더 좋고 더 자세한 답변은 @nawfal을 참조하십시오. 나는 더 단순하게 노력할 것입니다.
클래스의 멤버를 선언하므로 델리게이트를 고수해야합니다. 사용 delegate
은 더 설명적이고 구조적입니다.
Action/Func
유형은 전달을 위해 만들어 지므로 매개 변수 및 지역 변수로 더 많이 사용해야합니다.
그리고 실제로 둘 다 상속 Delegate
클래스입니다. Action 및 Func는 제네릭 형식이며 다른 매개 변수 형식을 사용하여 대리자를 간단하게 만듭니다. 그리고 delegate 키워드는 실제로 하나의 선언에서 Delegate로부터 상속받은 완전히 새로운 클래스를 생성합니다.
으로 MSDN을 했다, Func<>
그 자체가 미리 정의입니다 Delegate
. 처음으로 나는 이것에 대해 혼란스러워했습니다. 실험이 끝난 후 이해가 더 명확 해졌습니다. 일반적으로 C #에서는
Type
에 대한 포인터로Instance
.
동일한 개념이 적용됩니다.
Delegate
에 대한 포인터로Method
이것들과 사물의 차이점은 Delegate
예를 들어 OOP의 개념을 가지고 있지 않다는 것입니다 Inheritance
. 이 일을 더 명확하게하기 위해 저는
public delegate string CustomDelegate(string a);
// Func<> is a delegate itself, BUILD-IN delegate
//==========
// Short Version Anonymous Function
//----------
Func<string, string> fShort = delegate(string a)
{
return "ttt";
};
// Long Version Anonymous Function
//----------
Func<string, string> fLong = a => "ttt";
MyDelegate customDlg;
Func<string, string> fAssign;
// if we do the thing like this we get the compilation error!!
// because fAssign is not the same KIND as customDlg
//fAssign = customDlg;
프레임 워크의 많은 기본 제공 메서드 (예 : LINQ)는 Func<>
delegate 의 매개 변수를받습니다 . 이 방법으로 할 수있는 것은
Declare
Func<>
형식 의 대리자를Define
사용자 지정 대리자가 아닌 함수에 전달합니다 .
예를 들어 위의 코드에서 더 많은 코드를 추가합니다.
string[] strList = { "abc", "abcd", "abcdef" };
strList.Select(fAssign); // is valid
//strList.Select(customDlg); // Compilation Error!!
'ProgramingTip' 카테고리의 다른 글
Android의 자산 폴더 또는 원시 폴더에 파일을 쓰는 방법은 무엇입니까? (0) | 2020.11.13 |
---|---|
요소가 부모의 마지막 자녀 확인 (0) | 2020.11.13 |
EditText에서 int를 어떻게 짊어 지나요? (0) | 2020.11.13 |
웹 서버에서 설치할 수 없습니다. (0) | 2020.11.13 |
302 상대 URL로 리디렉션이 유효하거나 유효하지 않습니까? (0) | 2020.11.13 |