The Evolution of C# Part-II

68
The Evolution of C# 버버 버 버버 버버 버버버

description

사내 C# 세미나 Part-II 슬라이드입니다. 데모 코드는 https://github.com/gyuwon/csharp-seminar-demos/ 에 있습니다. 3.0 - Type Inference - Anonymous Classes - Extension Methods - Lambda Expressions - Expression Trees - Linq - IQueryable - OData 4.0 - Static Typing vs. Dynamic Typing - var vs. dynamic - System.Dynamic.ExpandoObject - System.Dynamic.DynamicObject - Optional Arguments - Named Arguments - Covariance & Contravariance 5.0 - Blocking Programming vs. Non-Blocking Programming - Asynchronous Methods(async & await) - Caller Information

Transcript of The Evolution of C# Part-II

Page 1: The Evolution of C# Part-II

The Evolution of C#버전 별 주요 특징

이규원

Page 2: The Evolution of C# Part-II

본 세미나의 목적

• C# 주요 변화과정 둘러보기• Remind

• 가려운 곳 긁기• 2%

Page 3: The Evolution of C# Part-II

본 세미나에서 다루는 것들

• C# 언어의 버전 별 발전 과정• C# 언어와 밀접한 .NET Framework 특징• C# 언어에 영향을 준 프로그래밍 언어들과의 비교

Page 4: The Evolution of C# Part-II

본 세미나에서 다루지 않는 것들

• C# 언어의 기초적인 문법 (if, foreach, using, try, lock, …)

• C# 언어와 직접적으로 관련되지 않은 .NET Framework 특징• C# 언어와 직접적으로 관련되지 않은 프레임워크 (TPL, WCF, Entity

Framework, …)

• 응용프로그램 플랫폼 (WPF, ASP.NET, …)

Page 5: The Evolution of C# Part-II

발표자

• 프로그래머• 통계학 학사 , 숭실대

(`97~`05)• Visual Studio 의 노예• 현 프리랜서• 위대한 ESM 팀 소속• 1989 년 BASIC 입문 on Ap-

ple IIe• 1991 년 C 입문 on 8086• 1992 년 음주 입문• 1997 년 C++ & Java 입문• 2005 년 C# 입문

[email protected]

http://justhackem.wordpress.com

http://facebook.com/gyuwon.yi

Page 6: The Evolution of C# Part-II

Keywords

1.0• Man-

aged

2.0• Generic

3.0• Linq

4.0• Dy-

namic

5.0• Async

Page 7: The Evolution of C# Part-II

3.0

All for Linq

Page 8: The Evolution of C# Part-II

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;

Page 9: The Evolution of C# Part-II

Anonymous Classes

• 컴파일러에 의해 자동으로 생성되는 클래스 (not in Run-time)

• 속성만으로 구성• 각 속성은 개체가 초기화될 때에만 설정 가능• ToString()

var obj = new {

Id = 1,

Name = "Tony Stark",

Email = "[email protected]"

};

Page 10: The Evolution of C# Part-II

DEMO

Generic Collections of Anonymously Typed Elements

Page 11: The Evolution of C# Part-II

Extension Methods

• 상속과 재 컴파일 없이 개체에 메서드를 추가• 대상 형식의 공개된 멤버에만 접근 가능• 인스턴스 메서드 문법을 사용하는 정적 클래스의 정적 메서드• 첫 번째 매개변수를 this 키워드로 수식

Page 12: The Evolution of C# Part-II

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

Page 13: The Evolution of C# Part-II

Lambda(λ) Expressions

• Anonymous methods

• Expression trees

• Argument(s) => Body

Page 14: The Evolution of C# Part-II

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;

Page 15: The Evolution of C# Part-II

Expression Trees

• 트리 like 자료구조로 코드를 표현• ≠ Delegate

• 컴파일러에 의해 생성• Expression API 를 사용한 구성• IQueryable<>

• DLR

Page 16: The Evolution of C# Part-II

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

Page 17: The Evolution of C# Part-II

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

Page 18: The Evolution of C# Part-II

Linq

• Language Integrated Query

• 프로그래밍 세계와 데이터 세계를 연결• [lɪŋk]

• 프로그래밍 언어로 데이터 처리• 지연된 실행• Fluent api

• Query expression

Page 19: The Evolution of C# Part-II

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);

Page 20: The Evolution of C# Part-II

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);

Page 21: The Evolution of C# Part-II

DEMO

Query Expression vs. Fluent Api

Custom Query Operation

Page 22: The Evolution of C# Part-II

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)

Page 23: The Evolution of C# Part-II

DEMO

Count() vs. Any()

Page 24: The Evolution of C# Part-II

IQueryable

• Expression Tree 로 표현되는 질의 명령• 명령을 번역하고 실행하는 QueryProvider

• QueryProvider 의 핵심 코드는 데이터 제공자에 의해 구현

Page 25: The Evolution of C# Part-II

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< >

Page 26: The Evolution of C# Part-II

IQueryable

Data Con-sumer

QueryableQuery

Provider

Data Provider

Data Source

Data Command

Programming Language Expression Tree

Page 27: The Evolution of C# Part-II

Programming Language

var query = from c in db.Con-tacts where c.Id == id select c;

Page 28: The Evolution of C# Part-II

Expression Tree

Query MethodCallExpressionN

Where

Arguments

0

1

{db.Contacts}: Object-Query

LogicalBinaryExpression

{c.Id} : PropertyExpres-sion

Left

{id}Right

Expression

Equal

NodeType

Method

Page 29: The Evolution of C# Part-II

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)

Page 30: The Evolution of C# Part-II

DEMO

IQueryable

Page 31: The Evolution of C# Part-II

OData

• 데이터 처리를 위한 웹 프로토콜• http://www.odata.org

• ASP.NET Web API[Queryable]public IQueryable<…> …()

Page 32: The Evolution of C# Part-II

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]

Page 33: The Evolution of C# Part-II

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

Page 34: The Evolution of C# Part-II

DEMO

OData

Page 35: The Evolution of C# Part-II

Take a break

Page 36: The Evolution of C# Part-II

4.0

Dynamic

Default Parameters and Name Arguments

Covariance and Contravariance

Page 37: The Evolution of C# Part-II

Static Typing vs. Dynamic Typing

Static Typing• 컴파일 타임 형식 검사• 개체가 생성될 때 형식 결정• 안정성 증대• 성능 최적화

Dynamic Typing• 런타임 형식 검사• 런타임 속성 및 행위 변경• 쉽고 빠른 코드 수정• 낮은 결합도• 단위 테스트를 통한 오류 검출

Page 38: The Evolution of C# Part-II

Dynamic in C#

• “dynamic” 키워드• 동적 언어의 특징 부여• 정적 형식 개체의 동적 멤버 바인딩• System.Dynamic.ExpandoObject

• System.Dynamic.DynamicObject

Page 39: The Evolution of C# Part-II

var vs. dynamic

var• 컴파일러에 의해 형식 유추• Anonymous Types

• IntelliSense

• 런타임 변수 형식 변경 불가

dynamic• Dynamic Typing

• 내부적으로 System.Object

• 명시적 형 변환 없는 멤버 접근• 런타임 변수 형식 변경 가능

Page 40: The Evolution of C# Part-II

DEMO

Dynamic Binding of Statically Typed Objects

Page 41: The Evolution of C# Part-II

ExpandoObject

• 런타임 멤버 추가 및 삭제• Hashing

• sealed

• 문자열 키 사전 기반 자료구조 대안

Page 42: The Evolution of C# Part-II

DEMO

ExpandoObject

Page 43: The Evolution of C# Part-II

DynamicObject

• 동적 개체 구현 기반 클래스• Interoperation

• public virtual bool Try…(…Binder binder, …)

Page 44: The Evolution of C# Part-II

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];

}

Page 45: The Evolution of C# Part-II

선택적 매개변수 (Optional Arguments)

• 기본값을 가진 매개 변수• 상수 식 또는 값 형식 기본 값• 선택적 매개변수는 모든 필수적 매개변수 뒤에 위치

Page 46: The Evolution of C# Part-II

명명된 매개변수 (Named Arguments)

• 이름을 사용한 인수 전달• 매개변수 순서에 구애 받지 않음• 명명된 매개변수는 모든 위치 기반 매개변수 뒤에 위치

Page 47: The Evolution of C# Part-II

DEMO

Optional Arguments and Named Arguments

Page 48: The Evolution of C# Part-II

Covariance

• <out T>

• If A → B

• IEnumerable<A> → IEnumerable<B>

Page 49: The Evolution of C# Part-II

Contravariance

• <in T>

• If A → B

• Action<B> → Action<A>

Page 50: The Evolution of C# Part-II

Covariance and Contravariance

• 인터페이스와 대리자 대상• 참조 형식 형식 매개변수에만 적용 가능

Page 51: The Evolution of C# Part-II

DEMO

Covariance & Contravariance

Page 52: The Evolution of C# Part-II

Take a break

Page 53: The Evolution of C# Part-II

5.0

Asynchronous

Caller Information

Page 54: The Evolution of C# Part-II

Blocking Manner

External Service

Work-ing

Waiting

Work-ing

Request

Response

Page 55: The Evolution of C# Part-II

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

Page 56: The Evolution of C# Part-II

Non-Blocking Manner in Server-Side

External Service

Work-ing

Work-ing

Request

Response

Thread Pool

Request

Response

Page 57: The Evolution of C# Part-II

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?

Page 58: The Evolution of C# Part-II

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!

Page 59: The Evolution of C# Part-II

Asynchronous Methods

async void/Task/Task<…> …(…){ … … await [Awaitable Statement] …}

Page 60: The Evolution of C# Part-II

Awaitable

• GetAwaiter()• INotifyCompletion { void OnCompleted(Action continuation); }• bool IsCompleted { get; }• GetResult()

• Task or Task<>

Page 61: The Evolution of C# Part-II

DEMO

Asynchronous Manner Client Application

Non-blocking Web Api

Page 62: The Evolution of C# Part-II

await 문법 조합

using (res)

{

await …

}

try

{

await …

}

catch

{

}

foreach (var e in …)

{

await …

}

if (…)

{

await …

}

Page 63: The Evolution of C# Part-II

Caller Infomation

• CallerMemberNameAttribute

• CallerFilePathAttribute

• CallerLineNumberAttribute

• 컴파일러 서비스

Page 64: The Evolution of C# Part-II

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 어려움

Page 65: The Evolution of C# Part-II

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

Page 66: The Evolution of C# Part-II

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

Page 67: The Evolution of C# Part-II

QnA

Page 68: The Evolution of C# Part-II

감사합니다