예를
class SomeClass
{
public event Action<int> SomeEvent;
}
를 들어, 일부 이벤트 일부 클래스가있는 경우는 다음 방법을 추가 이벤트를 생성 한 IL 코드는 다음과 같습니다
SomeClass.add_SomeEvent:
IL_0000: ldarg.0
IL_0001: ldfld UserQuery+SomeClass.SomeEvent
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: stloc.1
IL_0009: ldloc.1
IL_000A: ldarg.1
IL_000B: call System.Delegate.Combine
IL_0010: castclass System.Action<System.Int32>
IL_0015: stloc.2
IL_0016: ldarg.0
IL_0017: ldflda UserQuery+SomeClass.SomeEvent
IL_001C: ldloc.2
IL_001D: ldloc.1
IL_001E: call System.Threading.Interlocked.CompareExchange<Action`1>
IL_0023: stloc.0
IL_0024: ldloc.0
IL_0025: ldloc.1
IL_0026: bne.un.s IL_0007
IL_0028: ret
공지 사항 상기 그 메서드의 끝 부분에는 Interlocked.CompareExchange()
호출이 있고, 그 다음에 "같지 않은 경우 분기"가옵니다. 그래서 예, 가지가 있습니다. 따라서 순환 복잡성이 2가됩니다.
그런 이유는 무엇입니까? 그 이유는 대리자가 변경할 수 없다는 것입니다. 대리자에 메서드를 추가하면 원래 대리자는 수정하지 않지만 실제로는 기존 대리자와 제공된 메서드의 결합 된 대리자를 만들어 이벤트에 다시 할당합니다. Delegate.Combine을 참조하십시오.
게다가, 새로운 대리자와 이전 대리자 간의 스왑은 스레드로부터 안전해야하며, 그 이유는 Interlocked.CompareExchange입니다. 스왑에 실패하면 다시 시도하십시오.
가 나는 IL C에 #을 번역했습니다 있도록 :
public void add_SomeEvent(Action<int> arg1)
{
var local0 = this.SomeEvent;
IL_0007:
var local1 = local0;
var local2 = (Action<int>)Delegate.Combine(local1, arg1);
local0 = Interlocked.CompareExchange(ref this.SomeEvent, local2, local1)
if (local0 != local1) goto IL_0007;
}
정말 C 번호로 번역하는, 그건 '... 할 while' 루프가 될 것입니다. –
예, 'do..while' 루프가됩니다. 그러나 라벨과'goto's는 유효한 C#입니다. 가능한 한 일리노이와 비슷한 것으로두고 싶습니다. – vyrp