the evolution of c# part-i
DESCRIPTION
사내 C# 세미나 Part-I 슬라이드입니다. 데모 코드는 https://github.com/gyuwon/csharp-seminar-demos/ 에 있습니다. 1.0 - System.Object - Stack & Heap - Value Type & Reference Type - Boxing & Unboxing - Reference Type 추가 메모리 사용 - Delegates & Events - Interface 명시적 구현 2.0 - Generic - Anonymous Methods - Iterator Methods - NullableTRANSCRIPT
The Evolution of C#버전 별 주요 특징
이규원
본 세미나의 목적
• C# 주요 변화과정 둘러보기• Remind
• 가려운 곳 긁기• 2%
본 세미나에서 다루는 것들
• C# 언어의 버전 별 발전 과정• C# 언어와 밀접한 .NET Framework 특징• C# 언어에 영향을 준 프로그래밍 언어들과의 비교
본 세미나에서 다루지 않는 것들
• C# 언어의 기초적인 문법 (if, foreach, using, try, lock, …)
• C# 언어와 직접적으로 관련되지 않은 .NET Framework 특징• C# 언어와 직접적으로 관련되지 않은 프레임워크 (TPL, WCF, Entity
Framework, …)
• 응용프로그램 플랫폼 (WPF, ASP.NET, …)
발표자
• 프로그래머• 통계학 학사 , 숭실대
(`97~`05)• Visual Studio 의 노예• 현 프리랜서• 위대한 ESM 팀 소속• 1989 년 BASIC 입문 on Ap-
ple IIe• 1991 년 C 입문 on 8086• 1992 년 음주 입문• 1997 년 C++ & Java 입문• 2005 년 C# 입문
http://justhackem.wordpress.com
http://facebook.com/gyuwon.yi
Keywords
1.0• Man-
aged
2.0• Generic
3.0• Linq
4.0• Dy-
namic
5.0• Async
1.0
Managed
Value Type vs. Reference Type
Delegate and Event
System.Object
• 모든 클래스 , 구조체 , 열거형 , 대리자의 상위 형식Object
ValueType
Enum
String
Exception
Attribute
Int32
Double
DateTime TypeCode
Delegate
System.Object 멤버
public virtual int GetHashCode()
public virtual string ToString()
public virtual bool Equals(object obj)
public Type GetType()
protected object MemberwiseClone()
public static bool ReferenceEquals(object objA, object objB)
public static bool Equals(object objA, object objB)
메모리 관리
• Stack• 메서드 흐름에 따라 할당과 해제• 값 형식 개체• 개체 참조 (reference)
• Heap• new 구문을 사용하여 할당• GC 에 의해 해제• 참조 형식 개체• Boxing 된 값 형식 개체• 필드 + 3 * 4bytes(on a 32-bit platform)• Defragmentation
Defragmentation
파편화된 메모리 모형
• 전체 용량 : 10
• 사용량 : 6
• 3 메모리 블럭 할당 불가
파편화가 해결된 메모리 모형
• 전체 용량 : 10
• 사용량 : 6
• 3 메모리 블럭 할당 가능
Value Type vs. Reference Type
Value Type• Stack or Heap
• 작고 빠름• 대입 시 값 복사• Boxing
Reference Type• Heap
• 런타임 멤버 바인딩• 대입 시 참조 복사• 상속• Garbage Collection
Boxing and Unboxing
• 참조 형식으로 형변환• System.Object
• 인터페이스• 복사본 생성• 참조 형식의 특징
Boxing and Unboxing
int value1 = 10;
object h1 = value1; // BoxingIComparable h2 = value1; // Boxingobject h3 = h2; // Reference copy
int value2 = (int)h3; // Unboxing
Console.WriteLine(object.Equals(h1, h2)); // TrueConsole.WriteLine(object.Equals(h2, h3)); // TrueConsole.WriteLine(object.ReferenceEquals(h1, h2)); // FalseConsole.WriteLine(object.ReferenceEquals(h2, h3)); // True
…
h1
value1
h2
h3
value2
: Int32
: Int32
Stack Heap
Boxing
Unbox-ing
Refer-ence copy Boxing
DEMO
Value Type Performance
Garbage Collection
• Mark and Sweep
• Root 개체들로부터 개체 참조 그래프를 탐색하며 Mark
• Mark 된 개체들은 생존
4bytes(on a 32-bit platform)
• 참조 변수• 메모리 주소• ≠ Pointers in C/C++
refObj
valObj
Instance
…
…
4bytes
Stack Heap
struct MyValType { … }
class MyRefType { … }
MyValType valObj = new MyVal-Type();
MyRefType refObj = new MyRefType();
4bytes(on a 32-bit platform)
• Type 정보• 런타임 바인딩
• 가상 멤버• 인터페이스 구현
class MyRefType { … }
class MySubType : MyRefType { … }
MyRefType refObj = new MySub-Type();
…
refObj : MyRefType
Instance
…
MySub-Type
descrip-tion
Type informa-tion 4bytes
Stack Heap
4bytes(on a 32-bit platform)
• 개체 핸들• GC 과정에서 개체 이동• 개체 이동 부하 최소화
class MyRefType { … }
MyRefType ref1 = new MyRefType();
MyRefType ref2 = ref1;
object obj = ref2;ref2
ref1
In-stance
In-stance
Handle
obj
4bytes
Stack Heap
Delegates
• 메서드를 기억하고 호출을 대리하는 개체• 메서드 포인터 + 메타데이터 + 대상 개체 참조• 이벤트• 무명 메서드• Lambda expression
• Delegate Delegate.CreateDelegate(…, MethodInfo)
DEMO
Delegate Performance
Event
• 대리자에 대한 접근을 노출하는 add 메서드와 remove 메서드 집합• 외부에 +=(subscribe)/ -=(unsubscribe) 연산 노출• 이벤트 소유자만 이벤트 publish 가능
Event 구현 (Implicit vs. Explicit)
public class MyClass{ public event EventHandler Event1;
private EventHandler _event2; public event EventHandler Event2 { add { this._event2 += value; } remove { this._event2 -= value; } }}
Event Publishing
public event PropertyChangedEventHandler PropertyChanged;protected virtual void OnPropertyChanged(PropertyChangedEventArgs e){ if (this.PropertyChanged != null) this.PropertyChanged(this, e);}private string _name;public string Name{ get { return this._name; } set { this._name = value; this.OnPropertyChanged(new PropertyChangedEventArgs("Name")); }}
Event 메모리 사용
• 초기화된 인스턴스• 어떤 이벤트도 구독되지 않은 상태• 모든 이벤트 대리자 필드 값이 null 인 경우• 이벤트 수 * 4bytes(on a 32-bit platform)
• System.Windows.Forms.Control 클래스 이벤트 수 ≒ 70
EventHandlerList
• System.ComponentModel 네임스페이스• 이벤트 핸들러 대리자 목록 관리• 구독된 이벤트에 대해서만 메모리 할당• 이벤트 수가 적으면 비경제적• 이벤트 수가 많을수록 경제적
EventHandlerList 기반 구현
private EventHandlerList _events = new EventHandlerList();private static readonly object PropertyChangedKey = new object();public event PropertyChangedEventHandler PropertyChanged{ add { this._events.AddHandler(PropertyChangedKey, value); } remove { this._events.RemoveHandler(PropertyChangedKey, value); }}protected virtual void OnPropertyChanged(PropertyChangedEventArgs e){ var h = _events[PropertyChangedKey] as PropertyChangedEven-tHandler; if (h != null) h(this, e);}
Subscriber 참조
EventPublisher publisher = new EventPublisher();
publisher.Fire += new EventSubscriber("Mac").Handler;new EventSubscriber("Tosh");
GC.Collect();GC.WaitForPendingFinalizers();
publisher.RaiseFire();
Console.WriteLine("Finish");
Heap
Stack Walker
publisher
“Mac” “Tosh”
: Even-tHandler
WeakEventHandler
EventPublisher publisher = new EventPublisher();
new WeakEventHandler(publisher, new EventSubscriber("Mac"));new EventSubscriber("Tosh");
GC.Collect();GC.WaitForPendingFinalizers();
publisher.RaiseFire();
Console.WriteLine("Finish");
Heap
Stack Walker
publisher
“Mac” “Tosh”
: WeakEven-tHandler
: Even-tHandler
Weak Reference
I’m too weak. Don’t
kill me.
DEMO
Weak Event Subscription
Explicit Interface Implementation
interface IMyIntf1 { string Foo(); }
interface IMyIntf2 { string Foo(); }
class MyClass : IMyIntf1, IMyIntf2
{
public string Foo() { return "Hello"; }
string IMyIntf2.Foo() { return "World"; }
}
DEMO
Explicit Interface Implementation
Summary
• System.Object
• Garbage Collection
• Value Types and Reference Types
• Delegates and Events
• Explicit Interface Implementation
QnA
Take a break
2.0
Generic
Anonymous methods
Iterator methods
struct Nullable<T> where T : struct
Generic
• Reusable Code Definition
• Class, Interface, Delegate and Method
• Constraints
Code Definition
• 형식 안정적 코드 재사용• 어셈블리에 빌드• 런타임 코드 생성• 성능 향상• 값 형식에 대해 메모리 사용량 감소
Code Definition
: List<double> : List<string>
: double
: double
: double
…
: string^
: string^
: string^
…
: string
: string
: string
Class Definition
List<T>
: ArrayList
: object^
: object^
: object^
…
: double
: double
: double
DEMO
System.Collections.ArrayList vs. System.Collections.Generic.List<T>
Generic 제약조건
• 제네릭 코드에 사용할 수 있는 형식 매개변수를 제한• class/ struct
• Base Types
• new()
• 예 ) 매개변수가 없는 생성자를 제공하고 자신이 형식 매개변수인 IComparable<> 인터페이스를 구현하는 참조 형식where T : class, IComparable<T>, new()
Anonymous Methods
• Closure
• 부모의 이름 범위에 접근하는 내장 메서드• 이벤트 핸들러• 콜백 메서드
지역 변수 접근
int value = 0;
JobBuffer jobBuffer = new JobBuffer();
jobBuffer.Push(delegate() { value += 1; });
jobBuffer.Push(delegate() { value += 10; });
Console.WriteLine("Value: {0}", value);
jobBuffer.Flush();
Console.WriteLine("Value: {0}", value);
지역 변수 접근 구현
DEMO
Anonymous Methods
In Loops
Proc[] procs = new Proc[5];
for (int i = 0; i < procs.Length; i++)
{
procs[i] = delegate() { return i * i; };
}
foreach (Proc proc in procs)
Console.WriteLine(proc());
What do you ex-pect?
In Loops
Proc[] procs = new Proc[5];
for (int i = 0; i < procs.Length; i++)
{
int n = i;
procs[i] = delegate() { return n * n; };
}
foreach (Proc proc in procs)
Console.WriteLine(proc());
DEMO
Anonymous Methods in Loops
Iterator Methods
• 동일한 형식의 순차적 요소 집합을 제공하는 메서드• 컴파일러에 의해 생성되는 시퀀스• IEnumerable<T> 또는 IEnumerator<T>
• yield return
• yield break
• 데이터가 아닌 논리 ( 지연된 실행 )
• Linq operations
Arithmetic Progression 직접 구현
private readonly double _init;private readonly double _diff;private readonly int _n;
public ArithmeticProgressionEnumerable(double initialTerm, double dif-ference, int count){ this._init = initialTerm; this._diff = difference; this._n = count;}
public IEnumerator<double> GetEnumerator() { return new Enumerator(this); }IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); }
Arithmetic Progression 직접 구현
private ArithmeticProgressionEnumerable _source;private int _pos;
public Enumerator(ArithmeticProgressionEnumerable enumerable){ this._source = enumerable; this._pos = 0; }
public bool MoveNext(){ if (this._pos >= this._source._n) return false; this._pos++; return true;}
public double Current{ get { if (this._pos <= 0) throw new InvalidOperationException(); return this._source._init + this._source._diff * (this._pos - 1); }}
public void Reset() { this._pos = 0; }
Arithmetic Progression Iterator
IEnumerable<double> ArithmeticProgression(double initial-Term, double difference, int count)
{
for (int i = 0; i < count; i++)
yield return initialTerm + difference * i;
}
Arithmetic Progression Iterator 빌드
Delayed Execution
public IEnumerable<int> MyIterator(){ Console.WriteLine("Ready"); yield return 1; Console.WriteLine("Done");}
var s1 = MyIterator();var s2 = MyIterator();Console.WriteLine("I have 2 sequences.");foreach (int e in s2) Console.WriteLine(e);
DEMO
Delayed Execution
System.Nullable<>
• 값 형식 변수에 null 상태를 부여하는 값 형식 (Boxing and Unboxing)
• + : System.Boolean
• Nullable<type_name> or type_name?
• System.Nullable 도우미 static 클래스• GetType()
Nullable<> 핵심 코드
public struct Nullable<T> where T : struct{ private bool hasValue; internal T value;
public Nullable(T value) { this.value = value; this.hasValue = true; } public bool HasValue { get { return this.hasValue; } } public T Value { get { if (!this.HasValue) ThrowHelper.ThrowInvalidOperationExcep-tion(…); return this.value; } } public static implicit operator T?(T value) { return new T?(value); } public static explicit operator T(T? value) { return value.Value; }}
Nullable<> 산술 연산
double x = 2;double? y = null;Write(x * y); // nully = 10;Write(x * y); // 20
Nullable<> 대입 연산
int? x = null;double y;double? z;
y = x;// error CS0266: Cannot implicitly convert type 'int?' to 'double'.
y = (double)x;// InvalidOperationException: Nullable object must have a value.
z = x;
Nullable<> 비교 연산
int x = 10;
int y = 20;
int? z = null;
Console.WriteLine((x < y) == !(x >= y)); // True
Console.WriteLine((x < z) == !(x >= z)); // False
Summary
• Generic
• Anonymous Methods
• Iterator Methods
• Nullable
QnA
다음 시간에는…
• Linq 는 링큐인가 ? 링크인가 ?
• .NET 프로그래머에게 “ Duck typing” 의 의미• 비동기 I/O 하려면 Node.js 로 가야 하나 ?
감사합니다