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
3.0
All for Linq
Type Inference
• 주변 문맥을 통해 형식을 추론• 컴파일러에 의해 결정 (not in Run-time)
var obj = new DoYouThinkThatTheNameOfThisStructIsTooLong?();
Func<int, int> square = x => x * x;
Expression<Func<int, int>> exp = x => x * x;
Anonymous Classes
• 컴파일러에 의해 자동으로 생성되는 클래스 (not in Run-time)
• 속성만으로 구성• 각 속성은 개체가 초기화될 때에만 설정 가능• ToString()
var obj = new {
Id = 1,
Name = "Tony Stark",
Email = "[email protected]"
};
DEMO
Generic Collections of Anonymously Typed Elements
Extension Methods
• 상속과 재 컴파일 없이 개체에 메서드를 추가• 대상 형식의 공개된 멤버에만 접근 가능• 인스턴스 메서드 문법을 사용하는 정적 클래스의 정적 메서드• 첫 번째 매개변수를 this 키워드로 수식
Extension Methods
public static class DoubleExtensions{ public static double Cube(this double x) { return x * x * x; } public static double Pow(this double x, double y) { return Math.Pow(x, y); }}
double x = 10;Console.WriteLine(x.Cube()); // 1000Console.WriteLine(x.Pow(2.5)); // 316.227766016838
Lambda(λ) Expressions
• Anonymous methods
• Expression trees
• Argument(s) => Body
Lambda(λ) Expressions
Func<int, bool> func = delegate(int n) { return n > 20; };
Func<int, bool> func = (int n) => { return n > 20; };
Func<int, bool> func = (int n) => n > 20;
Func<int, bool> func = (n) => n > 20;
Func<int, bool> func = n => n > 20;
Expression<Func<int, bool>> expression = n => n > 20;
Expression Trees
• 트리 like 자료구조로 코드를 표현• ≠ Delegate
• 컴파일러에 의해 생성• Expression API 를 사용한 구성• IQueryable<>
• DLR
Expression Tree Decomposition
Expression<Func<int, bool>> expression = n => n > 20; expression: Lambda Expres-
sion
Parameters
: ParameterExpression
Name = “n”Type = System.Int32
Body : BinaryExpres-sionType = System.Bool-
eanNodeType = GreaterThan
ConstantExpression
Value = 20
LeftRight
Expression Tree Composition
ParameterExpression n = Expression.Parameter(typeof(int), "n");ConstantExpression twenty = Expression.Constant(20);BinaryExpression nGreaterThanTwenty = Expression.GreaterThan(n, twenty);var expression = Expression.Lambda<Func<int, bool>>(nGreaterThanTwenty, n);Console.WriteLine(expression);
Func<int, bool> func = expression.Compile();Console.WriteLine(func(10));
// Output// n => (n > 20)// False
Linq
• Language Integrated Query
• 프로그래밍 세계와 데이터 세계를 연결• [lɪŋk]
• 프로그래밍 언어로 데이터 처리• 지연된 실행• Fluent api
• Query expression
Query Expression vs. Fluent Api
Query Expressionfrom c in contacts
where c.Species == "Hu-man"
orderby c.Name
select c;
Fluent Apicontacts
.Where(c => c.Species == "Hu-man")
.OrderBy(c => c.Name);
Query Expression vs. Fluent Api
Query Expressionfrom s in strings
let split = s.Split(' ')
where
split.Length >= 2 &&
split[0][0] == split[1][0]
orderby
split[1]
select s;
Fluent Apistrings.Select(s => new{ Split = s.Split(' '), String = s}).Where(e => e.Split[0][0] == e.Split[1][0]).OrderBy(e => e.Split[1]).Select(e => e.String);
DEMO
Query Expression vs. Fluent Api
Custom Query Operation
Count() vs. Any()
Do notif (s.Count() == 0) …
if (s.Count() != 0) …
O(1) or O(n)
Doif (s.Any() == false) …
if (s.Any()) …
O(1)
DEMO
Count() vs. Any()
IQueryable
• Expression Tree 로 표현되는 질의 명령• 명령을 번역하고 실행하는 QueryProvider
• QueryProvider 의 핵심 코드는 데이터 제공자에 의해 구현
IQueryable API
System.Linq.Enumerablepublic static IEnumerable<TSource> Where<TSource>( this IEnumerable<TSource> source, Func<TSource, bool> predicate)
System.Linq.Queryablepublic static IQueryable<TSource> Where<TSource>( this IQueryable<TSource> source, Func<TSource, bool> predicate)
Expression< >
IQueryable
Data Con-sumer
QueryableQuery
Provider
Data Provider
Data Source
Data Command
Programming Language Expression Tree
Programming Language
var query = from c in db.Con-tacts where c.Id == id select c;
Expression Tree
Query MethodCallExpressionN
Where
Arguments
0
1
{db.Contacts}: Object-Query
LogicalBinaryExpression
{c.Id} : PropertyExpres-sion
Left
{id}Right
Expression
Equal
NodeType
Method
Data Command
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName],
[Extent1].[Email] AS [Email]
FROM [dbo].[Contacts] AS [Extent1]
WHERE ([Extent1].[Id] = @p__linq__0) AND (@p__linq__0 IS NOT NULL)
DEMO
IQueryable
OData
• 데이터 처리를 위한 웹 프로토콜• http://www.odata.org
• ASP.NET Web API[Queryable]public IQueryable<…> …()
OData
/api/Contacts/
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName],
[Extent1].[Email] AS [Email]
FROM [dbo].[Contacts] AS [Extent1]
OData
/api/Contacts/?$filter=length(FirstName) le 4
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName],
[Extent1].[Email] AS [Email]
FROM [dbo].[Contacts] AS [Extent1]
WHERE (CAST(LEN([Extent1].[FirstName]) AS int)) <= @p__linq__0
DEMO
OData
Take a break
4.0
Dynamic
Default Parameters and Name Arguments
Covariance and Contravariance
Static Typing vs. Dynamic Typing
Static Typing• 컴파일 타임 형식 검사• 개체가 생성될 때 형식 결정• 안정성 증대• 성능 최적화
Dynamic Typing• 런타임 형식 검사• 런타임 속성 및 행위 변경• 쉽고 빠른 코드 수정• 낮은 결합도• 단위 테스트를 통한 오류 검출
Dynamic in C#
• “dynamic” 키워드• 동적 언어의 특징 부여• 정적 형식 개체의 동적 멤버 바인딩• System.Dynamic.ExpandoObject
• System.Dynamic.DynamicObject
var vs. dynamic
var• 컴파일러에 의해 형식 유추• Anonymous Types
• IntelliSense
• 런타임 변수 형식 변경 불가
dynamic• Dynamic Typing
• 내부적으로 System.Object
• 명시적 형 변환 없는 멤버 접근• 런타임 변수 형식 변경 가능
DEMO
Dynamic Binding of Statically Typed Objects
ExpandoObject
• 런타임 멤버 추가 및 삭제• Hashing
• sealed
• 문자열 키 사전 기반 자료구조 대안
DEMO
ExpandoObject
DynamicObject
• 동적 개체 구현 기반 클래스• Interoperation
• public virtual bool Try…(…Binder binder, …)
Static Type Casting Hell
private void SomeMethod1(Geometry geometry)
{
BezierSegment bezier = (BezierSegment)((PathGeometry)((Combined-Geometry)geometry).Geometry1).Figures[0].Segments[0];
}
private void SomeMethod2(dynamic geometry)
{
BezierSegment bezier = geometry.Geometry1.Figures[0].Segments[0];
}
선택적 매개변수 (Optional Arguments)
• 기본값을 가진 매개 변수• 상수 식 또는 값 형식 기본 값• 선택적 매개변수는 모든 필수적 매개변수 뒤에 위치
명명된 매개변수 (Named Arguments)
• 이름을 사용한 인수 전달• 매개변수 순서에 구애 받지 않음• 명명된 매개변수는 모든 위치 기반 매개변수 뒤에 위치
DEMO
Optional Arguments and Named Arguments
Covariance
• <out T>
• If A → B
• IEnumerable<A> → IEnumerable<B>
Contravariance
• <in T>
• If A → B
• Action<B> → Action<A>
Covariance and Contravariance
• 인터페이스와 대리자 대상• 참조 형식 형식 매개변수에만 적용 가능
DEMO
Covariance & Contravariance
Take a break
5.0
Asynchronous
Caller Information
Blocking Manner
External Service
Work-ing
Waiting
Work-ing
Request
Response
Non-Blocking Manner in Client-Side
External Service
Work-ing
Work-ing
Request
Response
Main Thread
Work-ing
Work-ing
Work-ing
Work-ing
DispatchUser
Interaction
Non-Blocking Manner in Server-Side
External Service
Work-ing
Work-ing
Request
Response
Thread Pool
Request
Response
Blocking vs. Non-Blocking with TPL
Blocking semantics
int x = rs.Compute(rs.Get(key));
Console.WriteLine(x);
Non-blocking semantics
rs.GetAsync(key)
.ContinueWith(t1 => rs.ComputeAsync(t1.Result)
.ContinueWith(t2 => Console.WriteLine(t2.Result)));
Rocks or Sucks?
Through await Keyword
Non-blocking semantics with await keywordint x = await rs.ComputeAsync(await rs.GetAsync(key));
Console.WriteLine(x);
Blocking semanticsint x = rs.Compute(rs.Get(key));
Console.WriteLine(x);
int x = rs.ComputeAsync( rs.GetAsync(key));int x = rs.Compute ( rs.Get (key));
Rocks!
Asynchronous Methods
async void/Task/Task<…> …(…){ … … await [Awaitable Statement] …}
Awaitable
• GetAwaiter()• INotifyCompletion { void OnCompleted(Action continuation); }• bool IsCompleted { get; }• GetResult()
• Task or Task<>
DEMO
Asynchronous Manner Client Application
Non-blocking Web Api
await 문법 조합
using (res)
{
…
await …
…
}
try
{
…
await …
…
}
catch
{
}
foreach (var e in …)
{
…
await …
…
}
if (…)
{
await …
}
…
Caller Infomation
• CallerMemberNameAttribute
• CallerFilePathAttribute
• CallerLineNumberAttribute
• 컴파일러 서비스
INotifyPropertyChanged in C# 1.0
private int _value;public int Value{ get { return this._value; } set { this._value = value; this.OnPropertyChanged("Value"); }}public event PropertyChangedEventHandler PropertyChanged;protected virtual void OnPropertyChanged(string propertyName){ if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));}
오류 가능성 Refactoring 어려움
INotifyPropertyChanged in C# 3.0
private int _value;public int Value{ get { return this._value; } set { this.Set(() => this.Value, ref this._value, value); }}public event PropertyChangedEventHandler PropertyChanged;protected void Set<T>(Expression<Func<T>> expression, ref T field, T new-Value){ var body = expression.Body as MemberExpression; string propertyName = body.Member.Name; field = newValue; if (this.PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));}
비교적 높은 비용 하지만 refactorable
INotifyPropertyChanged in C# 5.0
private int _value;public int Value{ get { return this._value; } set { this.Set(ref this._value, value); }}public event PropertyChangedEventHandler PropertyChanged;protected void Set<T>(ref T field, T newValue, [CallerMemberName]string propertyName = null){ field = newValue; if (this.PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));}
낮은 비용 Refactorable
QnA
감사합니다
Top Related