C# 7.0 New Features

C# 7.0 새로운 기능 소개

튜플 ( Tuples )

자, C# 7.0에서 새롭게 달라진 튜플들을 알아보도록 하겠습니다.

Before Code


struct infos{ public int age; public string school;}
public infos Getinfo(string name) { ... }
 
var yosi = Getinfo("Z1젼7rl발ㅈr");
Console.WriteLine($"age: {yosi.age}, school: {yosi.school}"); 


튜플 반환 타입 ( Tuple return types )

반환 타입이 2개 이상인 함수를 만들 수 있습니다.

after code


public (int age, string school) Getinfo(string name) 
    ... 
}
 
var yosi = GetLatLng("Z1젼7rl발ㅈr"); 
Console.WriteLine($"age: {yosi.age}, school: {yosi.school}");


인라인 튜플 ( Inline tuples )

역시 아래와 같이 하면 인라인도 가능합니다.


var yosi = new (int age, string school) { age = 0 , school = "Go" };


레코드 타입 ( Record types )

이전에는 프로퍼티 떡칠을 하였다면 7.0에서는 그 불편함을 없애주었습니다.

Before Code


public class Point
{
    public int X { get ; set ;}
    public int Y { get ; set ;}
}


After Code


public class Point (int X = 1, int Y = 2);


하지만 알아두어야할 점이 있습니다.

1. readonly 필드를 가진 get-only 속성으로 생성이 되어 immutable이 되어있습니다.
2. 이 record type은 상속이 됩니다.
3. record type은 IEquatable<> 인터페이스에도 상속이 가능합니다.
4. Tostring 메소드를 이용하여 레코드의 각 멤버와 값을 나열합니다. ex) "Point (X: 1 Y: 2)"

불멸 타입 ( Immutable Types )

값이 바뀌면 안되는 클래스에 대해 사용하는 키워드입니다.
그저 클래스 앞에 immutable 키워드를 넣어주면 됩니다.


public immutable class Point
{
    public Point(int x, int y)
    {
        x = x;
        Y = y;
    }

    public int X { get; }
    public int Y { get; }
}


위의 코드로 중간에 변조를 불가능하게 되어 처음부터 끝까지 이 값을 쓸 수 있게 된다.
이런 형식을 대비하여 유용한 문법이 생겼다.


var yosi0 = new Point(1, 3);
var yosi1 = yosi0 with { X = 9 };


기존 인스턴스로부터 값을 바꿔 새로운 인스턴스로 사용하는 것이다.

Non-Null 참조 타입 ( Non-null reference types )

일반적으로 값 형식은 null을 가질 수 없으며, 반드시 기본 값을 가지게 되어 있습니다.
하지만 6.0에서 Nullable<>형식이 생겨 데이터 타입 뒤에 ? 만 붙이면 null을 가질 수 있게 되었습니다.


int a; // non-nullable value type
int? b; // nullable value type
string c; // non-nullable value type
string? d; // nullable value type 


non-null 처리를 하려면 데이터 타입 뒤에 ! 를 붙이면 null이 불가능한 참조 변수를 만들 수 있습니다. 
이는 제네릭과 클래스에도 적용이 가능합니다.


int a; // non-nullable value type
int? b; // nullable value type
string! c; // non-nullable reference type 
string d; // nullable value type

// Dictionary non-nullable reference type
Dictionary<string, List<MyClass>>! myDict;   


지역 함수 ( Local Functions )

블록 내에 잠깐 처리를 위해 람다식을 사용했던 분들이라면 아래와 같은 불편함을 겪을 것이라 예상할 수 있습니다.

1. 제네릭 사용 불가능
2. ref 및 out 사용 불가능
3. 가변 인자 사용 불가능

이를 해결할 수 있는 지역 함수 기능을 제공하였습니다.
C# 7.0 에서는 람다식에서 못한 한계를 해결 할 수 있습니다!


public int Calculate(int someInput)
{
    int Factorial(int i)
    {
        if (i <= 1)
            return 1;
        return i * Factorial(i - 1);
    }
    var input = someInput + ... // Other calcs

    return Factorial(input);
}


그리고 마지막으로 제일 기대되고 제 생각으로는 개쩌는 기능입니다.

패턴매칭 ( Pattern Matching )

C# 7.0에서 나온 재미나고 사용을 하게 된다면 형태에 의한 분기가 편해질거라 예상됩니다.

is 메서드로 매칭이 가능합니다.

상수 매칭


if ( x is 1 )
{
    return 1;
}


형태 매칭


if ( x is T t )
{
    return 1;
}


x를 T로 캐스팅 한 것이 t에 들어가며 x가 T의 특정 타입일 때에 매치됩니다.

속성 매칭


if ( x is T {X is int, Y is int} )
{
    return 1;
}


재귀 매칭


if ( x is T ( var a 1 ) )
{
    return 1;
}


또한 switch 문에서도 패턴 매칭이 가능합니다.


class Geometry();
class Triangle(int Width, int Height, int Base) : Geometry;
class Rectangle(int Width, int Height) : Geometry;
class Square(int width) : Geometry;
 
Geometry g = new Square(5);
switch (g)
{
    case Triangle(int Width, int Height, int Base):
        WriteLine($"{Width} {Height} {Base}");
        break;
    case Rectangle(int Width, int Height):
        WriteLine($"{Width} {Height}");
        break;
    case Square(int Width):
        WriteLine($"{Width}");
        break;
    default:
        WriteLine("<other>");
        break;
}


switch 문을 각 상속된 클래스와 맞는지 비교하여 해당될 때에 해당 케이스 문을 실행할 수 있습니다.
이번 C# 7.0 정말 기대되네요.



'0x0a Programming > 0x0d C#' 카테고리의 다른 글

C# 6.0 New Features  (0) 2016.07.19

C# 6.0 New Features

C# 6.0 새로운 기능 10가지 소개
* 예전에 써둔 글 옮기는 중입니다!


1. 엘비스 연산자

엘비스 연산자는 ? 앞에 있는 객체가 NULL인지 아닌지를 체크해서 NULL이면 NULL을 리턴하고, 그렇지 않으면 ? 다음 속성이나 메서드를 실행합니다.
만약 인덱서 혹은 배열 요소등을 접근할 경우에는 ?[] 과 같이 표현이 가능합니다.

Before Code


var PageName = "Z1젼7rl발ㅈr";
if(UserName != NULL)
{
PageName = _Name;
}

var PageName = UserName != null ? _Name : "Z1젼7rl발ㅈr";


After Code


var PageName = UserName?._Name ?? "Z1젼7rl발ㅈr";



2. 문자열 보간

이 문자열 보간 기능을 사용하기 위해서는 $ 을 전체 서식 문자열 앞에 추가해야합니다.

Before Code


int x = 1,y=2;

string str = string.Format("{0}, {1}", x, y);



After Code


int x = 1,y=2;

string str = $"{x},{y}";



3. 딕셔너리(사전) 초기화

딕셔너리를 초기화하는 스타일과 사용하는 스타일이 약간의 차이가 있습니다.
6.0 으로 올라오면서 이러한 스타일을 통일시켰는데요.
※ 이 초기화 기능은 6.0으로 올라오면서 해시테이블, 인덱서를 지원하는 모든 객체에서 사용 가능합니다.

Before Code


var InfoMe = new Dictionary<string, string>()
{
{ "PageName", "Z1젼7rl발ㅈr"},
{ "AdminCnt", "3 Persons"}
};
string PN = InfoMe["PageName"];


After Code


var InfoMe = new Dictionary<string, string>()
{
["PageName"] = "Z1젼7rl발ㅈr",
["AdminCnt"] = "3 Persons"
};
string PN = InfoMe["PageName"];


4. nameof 연산자

C# 6.0의 name of 연산자는 타입, 메서드, 속성 등의 이름을 리턴하는 것으로 하드 코딩을 하지 않게 도움을 줍니다.

하드 코딩에 의한 타이핑 오류 방지에 도움이 됩니다.


Before Code


public Point Add(Point point)

{

if(point == null)

{

throw new ArgumentNullException("point");

}

}



After Code

public Point Add(Point point)

{

if(point == null)

{

throw new ArgumentNullException(nameof(point));

}

}


5. using static 문

지금까지는 클래스명,속성명으로 사용했습니다.

하지만 C# 6.0에서는 using static 클래스명을 작성하면 클래스명 없이 메서드를 직접 사용할 수 있게 됬습니다.


Before Code


namespace Z1젼7rl발ㅈr

{

    class Program

    {

        static void Main(string[] args)

        {


            Console.WriteLine("Z1젼7rl발ㅈr");


        }

    }

}



After Code


using static System.Console;


namespace Z1젼7rl발ㅈr

{

    class Program

    {

        static void Main(string[] args)

        {


            WriteLine("Z1젼7rl발ㅈr");


        }

    }

}



6. 예외 필터

이 기능은 Visual Basic, F#에서는 지원되고 있었지만 C#에는 지금까지 지원되지 않았던 기능입니다.

예외 필터란 catch 블럭이 예외를 catch하기 전에 필터링 할 수 있도록 허용하는 기능입니다.

C# 6.0 문법에서는 catch 문 뒤에 추가적인 when 조건문을 사용하면 됩니다.


Before Code


try
{
...
}
catch (ConfigurationException e)
{
}
finally
{
}


After Code


try
{
...
}
catch (ConfigurationException e) when (e.IsServere)
{
}
finally
{
}


7. catch 및 finally 블럭에 await

5.0 에서 await 기능을 도입했었지만 catch 및 finally 블럭에서 await 사용은 지원하지 않았다.
하지만 6.0으로 올라오면서 이를 기본적으로 지원하게 되었다.
비동기 짱짱 await


Code


try
{
service = new ServiceClient();
await service.Save(data);
}
catch (Exception ex)
{
await LoggingService.Log(ex);
}
finally
{
await service.Close();
}


8. 자동 프로퍼티 초기화

이전에는 프로퍼티를 자동 생성하는 방법에서 초기 값을 설정하는 방법은 생성자를 만들어서 이를 해당 값에 할당하였습니다.

하지만 6.0에서는 곧바로 자동 속성을 만들면서 = "값" 을 통해 생성자 구현 없이 값을 할당할 수 있게 되었습니다.


Before Code


public class Z1젼7rl발ㅈr
{
    public autos()
    {
        PageName = "Z1젼7rl발ㅈr";
    }

    public string PageName { get; set; }

}


After Code


public class autos
{

    public string PostName { get; } = "Z1젼7rl발ㅈr";

}


9. 읽기 전용 자동 프로퍼티

이전에는 자동 프로퍼티는 항상 get과 set을 함께 사용하였습니다.

하지만 6.0에서는 읽기 전용의 자동 프로퍼티를 쓸 수 있게 되었습니다..

즉 get만을 사용할 수 있게 됬습니다..

※ 값을 할당하지 않으면 컴파일러는 자동으로 default 값을 할당합니다. 


Before Code


public class Z1젼7rl발ㅈr
{

    public string PageName { get; set; }

}


After Code


After Code :

public class Z1젼7rl발ㅈr
{

    public string PageName { get; }

}


10. 식으로 구성된 메서드

Statement Block을 사용하는 대신 간단한 함수식을 사용할 수 있는데 이를 Expression-bodied member 표현이라고 합니다.

이는 기존의 람다식과 유사한 것으로 속성이나 메서드 body를 간략한 람다식처럼 표현합니다.


Code


public Point Move(int x, int y) => new Point(X+x, Y+y);


이상 C# 6.0 새로운 기능 소개 글이였습니다.


'0x0a Programming > 0x0d C#' 카테고리의 다른 글

C# 7.0 New Features  (1) 2016.07.20

+ Recent posts