지난 포스트에 이어서...
var list = new List<int>(10);
var menu = new ToolStripMenuItem("메뉴");
for(int i=0; i<list.Count; i++) {
var subMenu = new ToolStripMenuItem("메뉴 항목");
subMenu.Click += ( (sender, args)=>{ subMenu_Click(sender, i); } ); // closure
}
void subMenu_Click(object sender, int idx)
{
MessageBox.Show(string.Format("{0}이 클릭됨", idx));
}
예상되는 결과는? i번째 subMenu를 누르면 i가 출력되지 않는다.
다음과 같이 변수를 한 번 복사하는 게 해결책이다:
for(int i=0; i<list.Count; i++) {
var subMenu = new ToolStripMenuItem("메뉴 항목");
int j=i; // 이거면 되지 않을까 했는데 진짜 됐음-_-乃
subMenu.Click += ( (sender, args)=>{ subMenu_Click(sender, j); } ); // closure
}
해결하고 나서 stackoverflow에 질문을 올렸는데
Google: passing parameter evenhandler value changes C#
이걸로 검색하니까 금방 나옴.
역시 원리는 안 찾아보고 하니까 이유는 모른다.
아래 링크에 이유가 있다고 하는데 읽기는 귀찮다.
http://stackoverflow.com/questions/2226510/closures-in-c-sharp-event-handler-delegates
http://stackoverflow.com/questions/271440/c-sharp-captured-variable-in-loop
Monday, May 27, 2013
Sunday, May 26, 2013
Parameter 전달: Capturing Variables with Closures [Event handler]
var cc = new CustomClass();
var menu = new ToolStripMenuItem("메뉴 항목");
menu.Click += ( (sender, args)=>{ edit_Click(sender, cc); } ); // closure
void menu_Click(object sender, CustomClass cc)
{
cc.DoSomething();
}
원리는 귀찮아서 안 찾아보고 있는데 어쨌든 편하게 된다.
EventHandler<CustomClass> ...
void menu_Click(object sender, EventArgs<CustomClass> e)
{
e.
}
이거보단 훨씬 편하다.
var menu = new ToolStripMenuItem("메뉴 항목");
menu.Click += ( (sender, args)=>{ edit_Click(sender, cc); } ); // closure
void menu_Click(object sender, CustomClass cc)
{
cc.DoSomething();
}
원리는 귀찮아서 안 찾아보고 있는데 어쨌든 편하게 된다.
EventHandler<CustomClass> ...
void menu_Click(object sender, EventArgs<CustomClass> e)
{
e.
}
이거보단 훨씬 편하다.
Wednesday, May 22, 2013
HashSet
HashSet<T>은 C#에서 Set 대용으로(ie, 중복을 허용하지 않는 컬렉션) 흔히 쓰는데, equality를 hash code를 이용해서 검증하기 때문에 Object.GetHashCode()를 오버라이딩해 주어야 한다.
문제는 어느 인터페이스를 구현할 것인가이다. 구글에서 대충 검색하다 보면 IEqualityComparer<T>와 IEquatable<T>이 나타날 텐데, 감으로는 IEquatable<T>인 것 같지만(맞음) 과연 IEqualityComparer<T>는 무엇인가 하는 궁금증이 생긴다.
(사실 이 이유만은 아니다. Visual Studio에서 IEquatable의 정의를 따라가 보면,
bool Equals(T other)
만 있고 GetHashCode가 없어서 IEquatable<T> 구현 없이
그냥 Equals와 GetHashCode 를 override하고 말겠다는 생각이 든다...*)
어찌됐든, 두 인터페이스 중 어느 것을 써야 하는가에 대해서는, 아래 문서가 이를 잘 설명하고 있는데, 특히 마지막 답변이 이해하기 쉬운 예제와 함께 잘 설명하고 있다.
http://stackoverflow.com/questions/9316918/what-is-the-difference-between-iequalitycomparert-and-iequatablet
1. class T : IEquatable<T> 형태로 쓴다.
* class MyClass : IEquatable<T> 형태는 (대개) 의미가 없다.
* public bool Equals(T other)를 구현하면 된다.
- Object.Equals(Object o)에 비해서 parameter가 T가 되고(캐스팅이나 as가 필요 없어짐#),
override 키워드를 안 써도 경고문이 뜨지 않는 장점이 있다. <주>
* ==, !=, GetHashCode와 nongeneric Equals도 오버라이딩해야 한다.
- ...라고는 하는데 GetHashCode()만 해도 HashSet을 쓰는 데는 별 문제가 없다(아직까지는...).
2. IEqualityComparer는 특수한 상황에서만 쓰이는 동일성 비교 policy를 만들 때 쓴다. 예를 들어 특정 '조건을 만족하면 같은 것으로 치는' 상황이다. HashSet을 예로 들면, 평소에는 유일성이 인정되는 객체는 무조건 다 받아주다가(Add), 어떤 상황이 되면, 특정 조건을 만족하는 객체는 무조건 받지 않는 것이다.
class Person {
public int Age;
} // Equals를 재정의하지 않았으므로 ReferenceEquals가 호출될 것이다.
class AgeEqualityTester : IEqualityComparer<Person> {
public bool Equals(Person x, Person y) { return (x.Age==y.Age); }
public int GetHashCode(Person p) { return p.Age; }
}
var people = new Person[] {new Person {age=23} };
var person = new Person() { age=23 };
var b1 = people.Contains(person); //FALSE;
var b2 = people.Contains(person, new AgeEqualityTester()); //TRUE
여기서 ICollection.Contains() 메서드의 새로운 사용법을 배울 수 있다 :)
Person/People 예는 이해하기는 쉬운데 별로 재미는 없다. 이런 걸 생각해 보자:
복잡한 weighted graph data structure가 있다. 이것의 개략적인 모양을 2차원 화면에 그리려 하는데, 모든 edge를 나타내기는 어려워서, weight만 다르고 시작점과 끝점이 같은 edge가 여러 개 있을 때 그들 중 하나만 그리기로 하였다. --> 한 번 그린 edge를 set에 넣고 두 번째부터 안 그리든지, 그릴 set을 처음에 만들고 시작하든지 알아서...
그럼에도 모르겠는 거: IEquatable에 왜 GetHashCode()가 포함되어 있지 않은가?
*또한 IEquatable에 없는 GetHashCode 멤버 함수가 IEqualityComparer에는 있다! -_-
그런데 IEqualityComparer를 구현해서 HashSet에서의 동일성 검증에 사용하려 하면, 그렇게 되지도 않는다. 우선 Equals의 원형부터
public bool Equals(object objA, object objB)
로서, 마치 static 함수 같은 모양을 하고 있다(그러나 static은 아니다). C++/STL에서 operator overloading 하던 때의 짜증이 떠오른다... 이는 equality comparer라는 이름이 이미 암시하고 있기는 하다. 비교 대상이 아니라 '두 대상을 비교해 주는 무언가'라는 것.
# as는 이렇게 쓴다. 캐스트와 비슷하나, 변환이 실패했을 때 exception을 발생시키지 않고 그냥 null을 리턴한다.
class MyType {int m1; int m2;} // 모두 public 가정
public bool Equals(Object obj) {
var p = obj as MyType; // 캐스트와 비슷
if(p==null) return false;
return m1==p.m1 && m2==p.m2; // custom equality test 예제
}
문제는 어느 인터페이스를 구현할 것인가이다. 구글에서 대충 검색하다 보면 IEqualityComparer<T>와 IEquatable<T>이 나타날 텐데, 감으로는 IEquatable<T>인 것 같지만(맞음) 과연 IEqualityComparer<T>는 무엇인가 하는 궁금증이 생긴다.
(사실 이 이유만은 아니다. Visual Studio에서 IEquatable의 정의를 따라가 보면,
bool Equals(T other)
만 있고 GetHashCode가 없어서 IEquatable<T> 구현 없이
그냥 Equals와 GetHashCode 를 override하고 말겠다는 생각이 든다...*)
어찌됐든, 두 인터페이스 중 어느 것을 써야 하는가에 대해서는, 아래 문서가 이를 잘 설명하고 있는데, 특히 마지막 답변이 이해하기 쉬운 예제와 함께 잘 설명하고 있다.
http://stackoverflow.com/questions/9316918/what-is-the-difference-between-iequalitycomparert-and-iequatablet
1. class T : IEquatable<T> 형태로 쓴다.
* class MyClass : IEquatable<T> 형태는 (대개) 의미가 없다.
* public bool Equals(T other)를 구현하면 된다.
- Object.Equals(Object o)에 비해서 parameter가 T가 되고(캐스팅이나 as가 필요 없어짐#),
override 키워드를 안 써도 경고문이 뜨지 않는 장점이 있다. <주>
* ==, !=, GetHashCode와 nongeneric Equals도 오버라이딩해야 한다.
- ...라고는 하는데 GetHashCode()만 해도 HashSet을 쓰는 데는 별 문제가 없다(아직까지는...).
2. IEqualityComparer는 특수한 상황에서만 쓰이는 동일성 비교 policy를 만들 때 쓴다. 예를 들어 특정 '조건을 만족하면 같은 것으로 치는' 상황이다. HashSet을 예로 들면, 평소에는 유일성이 인정되는 객체는 무조건 다 받아주다가(Add), 어떤 상황이 되면, 특정 조건을 만족하는 객체는 무조건 받지 않는 것이다.
class Person {
public int Age;
} // Equals를 재정의하지 않았으므로 ReferenceEquals가 호출될 것이다.
class AgeEqualityTester : IEqualityComparer<Person> {
public bool Equals(Person x, Person y) { return (x.Age==y.Age); }
public int GetHashCode(Person p) { return p.Age; }
}
var people = new Person[] {new Person {age=23} };
var person = new Person() { age=23 };
var b1 = people.Contains(person); //FALSE;
var b2 = people.Contains(person, new AgeEqualityTester()); //TRUE
여기서 ICollection.Contains() 메서드의 새로운 사용법을 배울 수 있다 :)
Person/People 예는 이해하기는 쉬운데 별로 재미는 없다. 이런 걸 생각해 보자:
복잡한 weighted graph data structure가 있다. 이것의 개략적인 모양을 2차원 화면에 그리려 하는데, 모든 edge를 나타내기는 어려워서, weight만 다르고 시작점과 끝점이 같은 edge가 여러 개 있을 때 그들 중 하나만 그리기로 하였다. --> 한 번 그린 edge를 set에 넣고 두 번째부터 안 그리든지, 그릴 set을 처음에 만들고 시작하든지 알아서...
그럼에도 모르겠는 거: IEquatable에 왜 GetHashCode()가 포함되어 있지 않은가?
*또한 IEquatable에 없는 GetHashCode 멤버 함수가 IEqualityComparer에는 있다! -_-
그런데 IEqualityComparer를 구현해서 HashSet에서의 동일성 검증에 사용하려 하면, 그렇게 되지도 않는다. 우선 Equals의 원형부터
public bool Equals(object objA, object objB)
로서, 마치 static 함수 같은 모양을 하고 있다(그러나 static은 아니다). C++/STL에서 operator overloading 하던 때의 짜증이 떠오른다... 이는 equality comparer라는 이름이 이미 암시하고 있기는 하다. 비교 대상이 아니라 '두 대상을 비교해 주는 무언가'라는 것.
# as는 이렇게 쓴다. 캐스트와 비슷하나, 변환이 실패했을 때 exception을 발생시키지 않고 그냥 null을 리턴한다.
class MyType {int m1; int m2;} // 모두 public 가정
public bool Equals(Object obj) {
var p = obj as MyType; // 캐스트와 비슷
if(p==null) return false;
return m1==p.m1 && m2==p.m2; // custom equality test 예제
}
Tuesday, May 21, 2013
Sunday, May 12, 2013
Thursday, May 9, 2013
Short-Circuit Evaluation
Short-circuit evaluation
여러(n) 개의 msg 발생기가 있고,
1) 그들 중 하나라도 발생하면 목적 프로그램(A)을 실행
2) 그들 중 모두가 발생해야 목적 프로그램(A)을 실행
하는 두 시나리오를 생각하자.
1)과 2) 모두 bool 값(B)에 따라 A의 실행 여부를 결정하되,
1)은 n-ary Or,
2)는 n-ary And
에 의해서 bool 값이 계산되는 것이다.
주의할 것은 사실 B값은 boolean 값이 아니라 enum {Undetermined, False, True} 값이라는 것.
그리고 B값을 계산하는 데 필요한 인수들도 그렇다는 것.
2)의 경우에는 그대로 두어도 문제가 없다.
n=3인 경우에 대해 생각하면, [U/U/U]가 [T/T/T]가 되면 A를 실행하고, 하나라도 F가 나타나는 순간 실행을 포기하면 된다. 그 외의 경우에는 무한 대기한다.
1)의 경우에는 short-circuit evaluation을 지원하지 않으면 문제가 된다.
마찬가지로 n=3에 대해 생각하면, [T/U/U]가 됐을 때 A를 실행하지 않고 U가 T 또는 F로 바뀔 때까지 무한 대기하는 것이다. 이것은 처음에 목적한 "하나라도 발생하면 A 실행"에 맞지 않는다.
이것저것 기능을 추가하다 보니,
C++(null pointer를 피하는 데 유용하다)와는 전혀 다른 이유로 short-circuit evaluation이 필요하게 되었다.
위키를 보니 재미있는 내용이 있는데, &&, ||는 short-circuit operator이지만
bitwise operator인 &, |는 eager operator이다. (당연한가?)
위키를 보니 재미있는 내용이 있는데, &&, ||는 short-circuit operator이지만
bitwise operator인 &, |는 eager operator이다. (당연한가?)
Language | Eager operators | Short-circuit operators | Result type |
---|---|---|---|
ABAP | none | and , or | Boolean1 |
Ada, Eiffel | and , or | and then , or else | Boolean |
ALGOL 68 | and, &, ∧ ; or, ∨ | andf , orf (both user defined) | Boolean |
C2 | none | && , || , ? [1] | Numeric (&& ,|| ), opnd-dependent (? ) |
C++3 | & , | | && , || , ? [2] | Boolean (&& ,|| ), opnd-dependent (? ) |
Go, OCaml, Haskell | none | && , || | Boolean |
C#, Java, | & , | | && , || | Boolean |
Subscribe to:
Posts (Atom)
"Gossip Girl" star Michelle Trachtenberg dies at 39
미셸 트랙튼버그 하우스에서 심장 이식 받았던 환자로 나왔는데 현실에서는 간이식을 받았었구나 가십걸이나 버피더뱀파이어슬레이어 이제 정주행해 볼까... 블로그도 다시 살려 볼까 훠훠

-
텍스트박스에서 엔터를 치면 자동으로 입력되게 하려고 keyup 이벤트 핸들러를 등록했다. 잘 동작하는 듯했는데 alert창을 닫아도 닫아도 계속 열리는 것이다. 크롬이어서 다행이지 IE였으면 무한히 열렸을 거야...스페이스바로 눌러보길 잘했...
-
MathJax è Word MS Word 2007부터는 MathML을 문서에 바로 붙여넣을 수 있다. 이 블로그의 거의 대부분의 수식은 MathJax로 작성되어 있는데, 오른쪽 버튼 클릭하고 메뉴에서 MathML 또는 TeX 형식으로 ex...
-
진짜 되는 건 아니고 흉내낼 수는 있다. 새 창을 누르면 아무 것도 안 변한 것 같지만 PowerPoint 창 제목이 바뀌어 있다: 프레젠테이션1:2에서 :2 부분이 같은 파일을 연 창 여러 개 중 2번째라는 뜻이다('프레...