/ c# 7.0

C# 7.0

Binary literals and digit separators

int myNumber = 0b11111111;
int myNumber2 = 0b1111_1111_0000_1111;

int onMillion = 1_000_000;

Local function

static void Main(string[] args)
{
    MyNumbers(); 
    
    void MyNumbers()
    {
        int mynum = 0b1111_1111;
        Console.WriteLine($"my number: {mynum}");
    }
}
int myValue = 1; 
int Calc(int n) => (n < 2) ? myValue : Calc(n-1) + Calc(n-2);
Console.WriteLine(Calc(8));
public IEnumberable<T> Filter<T>(IEnumerable<T> source, Func<T, bool> filter)
{
    if (source == null) throw new ArgumentNullException(nameof(source));
    if (filter == null) throw new ArgumentNullException(nameof(filter));
    
    return Iterator(); 
    
    IEnumerable<T> Iterator()
    {
        forech(var element in source)
        {
            if (filter(element)) { yield return element; }
        }
    }
}

Tuple

Old Tuple: reference type, immutable(must be)

var person = new Tuple<string, string, int>("3 tuples", "C#", 2016);

var reynald = Tuple.Create("5 Tuples", "C#", "ilseokoh", 2018, 7.0);

var nestedTuple = new Tuple<int, int, int, int, int, int, int,
                      Tuple<string, string, double>>(2,3,4,5,6,7,8,
                      Tuple.Create("Nested", "C#", 7.0));
Console.WriteLine($"{nestedTuple.Rest.Item1}");
public static Tuple<string, string, int> GetTupleMethod() 
{
    var person = new Tuple<string, string, int>("tuple", "c#", 7.0);
    return person; 
}

New Tuple: value type(structs), mutable

Nuget에서 패키지를 받아와야 함.
PM> Install-Package "System.ValueTuple"

using System.ValueTuple;

class TupleSamples
{
    public (string, string, long) GetNewCS7Tuple() { 
        string name = "kevin oh";
        string title = "ilseokoh.com";
        long year = 2018;
        
        return (name, title, year); 
    }
}

...

private static void Cs7Tuple()
{
    TupleSamples ts = new TupleSamples(); 
    var person = ts.GetNewCS7Tuple(); 
    Console.WriteLine($"C# 7 Tuple - Author {person.Item1}, {person.Item2}, {person.Item3}");
}
class TupleSamples
{
    public (string name, string title, long year) GetNewCS7Tuple() { 
        string name = "kevin oh";
        string title = "ilseokoh.com";
        long year = 2018;
        
        return (name, title, year); 
    }
}

Deconstructors

(string authorName, string bookTitle, long pubYear) = GetNewCS7Tuple(); 

Console.WriteLine($"Author: {authorName}, Title: {booktitle}, Year: {pubYear}");
(var authorName, var bookTitle, var pubYear) = GetNewCS7Tuple(); 

var(authorName, bookTitle, pubYear) = GetNewCS7Tuple(); 
class Program
{
    static void Main(string[] args)
    {
        Comedian comedian = new Comedian("Kevin", "Oh");
        var (firstname, lastname) = comedian; 
        Console.WriteLine($"{firstname} {lastname}");
    }
}

public class Comedian
{
    public stirng Firstname;
    public string Lastname; 
    
    public Comedian(string firstname, string lastname)
    {
        this.Firstname = firstname; 
        this.Lastname = lastname;
    }

    public void Deconstuct(out string firstname, out string lastName) { 
        firstName = FirstName; 
        lastName = LastName;
    }
}

Is expressions with patterns

if (a is Performer p1)
    Console.WriteLine($"This actor {p1.Name} is a performer.");
else ConsoleWriteLine($"This actor is not a performer.");

if (a is Musisian) 
    Console.WriteLine($"This actoris a musician.");
else ConsoleWriteLine($"This actor is not a musician.");

switch statement with patterns

switch(m)
{
    case Performer performer when (performer.Age == 33): 
        Console.WriteLine($"The performer {performer.Name}");
    case Musician musician when (musician.Age == 25): 
        Console.WriteLine($"The Performer {musician.Name}");
    case Musician musician:
        Console.WriteLine($"The Musician is unknown");
    default: 
        Console.WriteLine("Not Found"); 
    case null: 
        throw new ArgumentNullException(nameof(m));
}

Ref returns

원래 ref 용도

static void AddByRef(long a, long b, ref long total)
{
    total = a + b;
}

static void TestRef1()
{
    long total = 0;
    AddByRef(15, 10, ref total); 
    Console.WriteLine(total); // 25
}
public ref string FindActor(int index, string[] names)
{
    if (names.Length > 0) 
        return ref names[index];
        throw new IndexOutOfRangeException($"{nameof(index)} not found");
}

static void TestRef2() 
{
    string[] actors = {"Ben", "Jennifer", "Tom", "Matt", "Jackie"}; 
    int positionInArray = 2; 
    
    ref string actor3 = ref new Program.FindActor(positionInArray, actors);
    
    Console.WriteLine($"Origin: {actor3}"); // Tom
    
    actor3 = "Kevin"; 
    
    Console.WriteLine($"Changed: {actors[positionInArry]}"); // kevin
}

Out variables

static void main(string[] args) 
{
    CreateName(out var firstname, out var lastName); 
    Consoel.WriteLine($"{firstname}, {lastName}");
}

private static void CreateName(out string firstName, out string lastName) 
{
    firstName = "Kevin";
    lastName = "Oh";
}

Generalized async return types

nuget
PM> Install-Package System.Threading.Tasks.Extensions

ValueTask는 sturct.

private int GetCharacterCount()
{
    int count = 0;
    using (StreamReader reader = new StreamReader("Data.txt"))
    {
        string content = reader.ReadToEnd();
        count = content.Length;
        Thread.Sleep(5000);
    }
    return count;
}

private async ValueTask<int> ProcessFile() {
    Task<int> task = new Task<int>(GetCharacterCount);
    task.Start();
    return await task;
}

More expression bodied members

Constructor

//public Person(string name)
//{
//    Name = name;
//}

public Person(string name) => Name = name;

Full property

private string _name;
public string Name
{
    get => _name;
    set => _name = value;
}

Destructor

//~Person()
//{
//    Console.WriteLine("Destructor was called!");
//}

~Person() => Console.WriteLine("Destructor was called!");

Throw expressions

private string _name;
public string Name
{
    get => _name;
    set => _name = value ?? throw new ArgumentNullException(nameof(Name), message: "New name must not be null");
}

Null Coalescing Expression

public Person(string name) => Name = name ?? throw new ArumentException(name);

Conditional Expression

public string GetFirstname() { 
    var parts = Name.Split(new string[] {" "}, StringSplitOptions.None);
    return (parts.Length > 0) ? parts[0] : throw new InvalidOperationException("No name");
}

Lambda Expression

public string GetLastname() => throw new NotImplementationException();