설정/이벤트 처리기 제거합니다.Net
-
03-07-2019 - |
문제
그래서 나와 함께 갇혀 고정/유지 다른 프로그래머 코드(blech)
나 회사의 교수가 규칙 "If it ain't 을 끊었지요." 그래서 depsite 을 변경하고 싶은 뭔가가 모든 시간에 걸쳐 온 끔찍한 코드,나는 나 자신만 제한되는 변화는 절대 가능한 최소량의 코드를 필요한 수정이 있습니다.하지만 일부 경우에는 내가 정말 필요가 무언가를 이해하기 전에 그것을 따르도록/변경합니다.
이 조금 여기:
region.LineSelected = (x) => { };
과 궁금의 경우와 같다:
region.LineSelected = null;
내가 원하는 100%긍정적인 것의 첫 번째 라인을 내가 가기 전에 변경하는 방법이 있습니다.
해결책
주제에 대한 나의 현재 의견에 따라 편집
그들은 동일하지 않습니다. Lambda 버전은 빈 익명 방법에 이벤트 핸들러를 추가하고 있습니다. 이를 통해 다른 코드는 NULL인지 (예 : 리스너가 없음) 걱정하지 않고 LineSelected ()를 자유롭게 올릴 수 있습니다.
예를 들어.
var lineSelected = this.LineSelected;
if (lineSelected != null)
{
lineSelected(EventArgs.Empty);
}
위의 진술은 IF 이후 이벤트가 발생하기 전에 다른 스레드에서 선출 된 라인에서 구독을 해제하면 NullReferenceException을 던질 수 있습니다. 임시 변수에 라인 선택을 할당 한 다음 구독되지 않은 이벤트 리스너를 호출 할 수있는 올릴 수 있습니다. 이벤트 핸들러를 로컬 변수에 할당하는 것은 NULL 대의원을 처리하는 권장 방법입니다.
빈 대표단을 추가함으로써 다른 코드는 항상 NullReferenceException에 대한 두려움없이 라인 선택을 호출 할 수 있습니다. 멀티 캐스트 이벤트 대의원을 로컬 변수에 할당하면 다른 스레드로 값을 수정할 수 없습니다.
다른 팁
첫 번째 코드 라인을 가야 할 이유가 있다고 생각할 수 없습니다. 내가 생각할 수있는 유일한 것은 라인 선택 이벤트를 올릴 때, 클래스에 첫 번째 코드 줄이 있다면 라인 선택 이벤트가 null인지 확인할 필요가 없습니다. 즉:
if (this.LineSelected != null)
{
LineSelected(this,new EventArgs());
}
대신, 당신은 null 검사없이 이벤트를 올릴 수 있습니다.
그러나 두 번째 코드 라인을 사용하면 널을 확인해야합니다.
는 이벤트를 처리기는 간단한할 수 있습니다.(이벤트 handler 을 수정해야와+=및=을 연결 및 분리 이벤트).
으로 주석 처리되기 전에,설정 대리인이 시설을 빈 처리기는 것을 의미 null 검사해야 하지 않을 수행하기를 호출하기 전에 사용자 대리인(고 가정하면 아무것은 그것을 설정할 수 있습니다 null).
이 호출할 수 있도록 코드를 더욱 편리하지만,그것은 혼동하지 말아야 되는 것으로 성능을 개선(제거를 확인하기 위해 필요 null).일반적으로의 오버헤드 대리자 메소드 호출 될 것보다 유의하게 높 null 확인합니다.될 수 있습 몇 가지 시나리오를(예를 들면 대리인은"진짜"구현 시간의 99.99%)는 피 null 체크인 개선할 수 있는 성능을 가지고 있지만 상상하기 어렵다는 시나리오의 작은 조금의 성과 차이가 있을 수 있습 문제를 충분히 가치가 그것없는 것 또한 보증을 제거 대리인 호출은 전적으로 찬성의 무언가를 더 효율적입니다.
나는 이것이 모든 이벤트에서 무효 점검을 피하는 기술이라고 생각합니다.
라인 선택 이벤트 레이징 코드에 적절한 NULL 점검이 없으면 예외가 발생합니다.
region.LineSelected = null;
/* no event handlers added to LineSelected */
class Region {
void OnLineSelected() {
// Null error!
LineSelected();
}
}
그러나 빈 없음 효과 핸들러가 추가되면 이벤트에 핸들러를 추가하지 않더라도 빈 핸들러가 항상 첨부되어 있지 않더라도 위의 코드는 잘 작동합니다.
Richard와 Andrew가 말한 것을 확장하기 위해, 그것은
region.LineSelected = delegate {};
즉, 이벤트를 제기 할 때 널을 먼저 확인할 필요가 없습니다. 대의원이 있기 때문에 (작은 성능 히트의 가격으로)
아니요 같은 것이 아닙니다. 첫 번째 줄이 지정됩니다. LineSelected
빈 대표단과는 매우 다릅니다 null
.
차이점을 발견하는 가장 쉬운 방법은 Lambda 구문을 사용할 때 컴파일러가 귀하를 대신하여 생성하는 코드를 보는 것입니다. 이 코드 :
using System;
class Program
{
static void Main()
{
Action<int> func0 = (x) => { };
Action<int> func1 = null;
}
}
정말로 이것으로 컴파일합니다.
internal class Program
{
// Methods
private static void Main()
{
Action<int> func0 = delegate (int x) {
};
}
}
컴파일러는 제거하기에 충분히 똑똑했습니다 func1
그것이 설정된대로 null
다른 곳에서는 언급되지 않았습니다. 그러나 그것을 주목하십시오 func0
여전히 남아 있고 대의원에게 설정되어 있지만 그럼에도 불구하고는 아무것도하지 않지만 null
.
이벤트 핸들러가 설정되어 있기 때문에 동일하지 않습니다.
라인 선택을 노출시키는 수업을 잊어 버린 수업을 잊어 버리십시오.
if( LineSelected != null )
LineSelected(...)
해당 클래스가 라인 선택을 호출하고 아무도 듣지 않으면 NullReferenceException을 던질 것입니다.
인종 조건을 피하기 위해 (내부) 할 수도 있습니다.
var event = 라인 선택; if (event! = null) 이벤트 (...