📜 ⬆️ ⬇️

C # - is there something extra?

Everything will be fast. This speech by Anatoly Levenchuk , recently haunts me. Successes of deep learning in the last year suggest that everything will change very quickly. For too long, wolf wolves were shouting "artificial intelligence," but he was not there. And so, when he finally comes to us, many people simply do not realize this, thinking that everything will end in another computer victory in the next intellectual game. Very many people, if not all of humanity, will be behind the board of progress. And this process is already running. I think that at this moment I will not be very interested in the question that is in the title of the article. But, while this moment has not yet arrived, I will try to raise this potentially controversial issue.

Programming for more than 25 years, I found quite a lot of different concepts, I was able to try something, I didn't even have time. Now I am watching with interest the language Go, which can be attributed to the successors of the “virtual language line” - Algol-Pascal-Modula-Oberon. One of the remarkable properties of this chain is that each subsequent language becomes simpler than the previous one , but no less powerful and expressive.

I think everyone understands what good is simple language. But nevertheless I will give these criteria, since they will emerge later:
')


Why then do complex languages ​​exist? It's all about expressiveness. If some construction allows you to briefly describe the necessary action, then this may well pay back the negative sides of the complication of the language.

For a relatively short time of its existence, the C # language has absorbed a significant number of different concepts reflected in its constructions. The speed of adding them sometimes scares. To me, since I am from C # almost from the very beginning, it is easier. But what are newbies who are just starting to learn? Sometimes I envy Java programmers where innovations are introduced into the language much more conservatively.

What has been added to the language is not really cut down with an ax. Of course, if you take a language that is widespread in narrow circles, you can allow yourself incompatibility between versions. Some "pranks" of reverse incompatibility can afford such a language as Python (when moving from the 2nd to the 3rd version). But not C # behind Microsoft. It seems to me that if the developers understood that with each new feature, the language becomes not only more convenient (in certain cases), but a little closer to its death from “obesity”, the comments would be a little less enthusiastic than it is in The first line of feedback on innovations C # 7 .

What is described below is just my speculation on whether this is really a useful thing. Of course, this may be a matter of taste and not everyone will agree with me (see spoilers). And in any case, it will remain in C # forever ... Well, until the moment of singularity, at least.

A list of added language features by version can be found here: C # Features added in versions . I will not touch version 2.0, I'll start with 3.0.

Lyrical memories
Practically any phenomenon, fact, language feature, has both positive and negative sides. What assessments we give to this depends a lot on our subjective characteristics, and another person can evaluate the same thing in the opposite way. Not only is it natural, most likely, these estimates in both cases will be correct. Just for different people. In the spoilers further try to show examples of such differences.


C # 3.0


Implicitly typed local variables


var i = 5;
var s = "Hello";
var d = 1.0;
var numbers = new int[] {1, 2, 3};
var orders = new Dictionary<int,Order>();

var. Java («Var val Java?», « «var» Java: , »)

, ( ). , , . , . , , , JavaScript-, .

:

List<Pair<String, Double>> scores = seeker.getScores(documentAsCentroid);
...
foreach(Pair<String, Double> score in scores)


(Pair<String, Double>) , . – ( , ). . Java, C#, Type (typedef C). C# using, - :

using StopWordsTables = System.Collections.Generic.List<System.Collections.Generic.Dictionary<string, string>>;


, , StopWordsTables. , …

typedef, .

, var , (.., ) . Code Agreement ( ). . Var . .

— var . . , , , , . Type/typedef .

– var, , Go? “=” “:=”, , . . … , type Go , .

— var C# . typedef.

var , , - .

Object and collection initializers


var r = new Rectangle {
   P1 = new Point { X = 0, Y = 1 },
   P2 = new Point { X = 2, Y = 3 }
};
List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

, . .

Auto-Implemented properties


,
public Class Point {
   private int x;
   private int y;
   public int X { get { return x; } set { x = value; } }
   public int Y { get { return y; } set { y = value; } }
}

:
public Class Point {
   public int X { get; set; }
   public int Y { get; set; }
}

, ? , Java , . , ( ) .

Anonymous types


var p1 = new { Name = "Lawnmower", Price = 495.00 };
var p2 = new { Name = "Shovel", Price = 26.95 };
p1 = p2;

. , 1 , . . , , . , , ( , JSON, , ).

Extension methods


namespace Acme.Utilities
{
   public static class Extensions
   {
      public static int ToInt32(this string s) {
         return Int32.Parse(s);
      }
      public static T[] Slice<T>(this T[] source, int index, int count) {
         if (index < 0 || count < 0 || source.Length – index < count)
            throw new ArgumentException();
         T[] result = new T[count];
         Array.Copy(source, index, result, 0, count);
         return result;
      }
   }
}


using Acme.Utilities;
...
string s = "1234";
int i = s.ToInt32();               // Same as Extensions.ToInt32(s)
int[] digits = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int[] a = digits.Slice(4, 3);      // Same as Extensions.Slice(digits, 4, 3)

. , () .

Query expressions


LINQ. ! , , - . , LINQ , . ? - (), SQL-, .

string[] people = new [] { "Tom", "Dick", "Harry" };
//     
var filteredPeople = from p in people where p.Length > 3 select p; 
//     
var filteredPeople = people.Where (p => p.Length > 3); 


:



WPF. , XML. . , — , XML? . , — , . .
, LINQ — , .

Lambda expressions


x => x + 1                     // Implicitly typed, expression body
x => { return x + 1; }         // Implicitly typed, statement body
(int x) => x + 1               // Explicitly typed, expression body
(int x) => { return x + 1; }   // Explicitly typed, statement body
(x, y) => x * y               // Multiple parameters
() => Console.WriteLine()      // No parameters

, C# , . , . .

Expression trees


LINQ Lambda.

Partial methods


. — .

,
-61, , . , , , . 4 ( ) (, ) , , «» .

— , , « » 0010 . , 18011 , , (16 ). ? 8 , 8 . / . , .

, 1502. IBM-PC , , MS DOS, . , .

, . . , . , — . 1502 (x86) ( ), 0010 (PDP-11). . , . — , DATA, . ! — . .

, , ( ), . , , ( — ). , , — . , ! , , — - , , ( — 25 ).

- , , -, — . ( ). — .


C# 4.0


Dynamic binding


—
var doc = new XmlDocument("/path/to/file.xml");
var baz = doc.GetElement("foo").GetElement("qux");


dynamic doc = new XmlDocument("/path/to/file.xml");
var baz = doc.foo.qux;

, , . dynamic — , . — . , , . , (, ). , , . — - , . . . , . , , .

Named and optional arguments


class Car {
  public void Accelerate(
    double speed, int? gear = null, 
    bool inReverse = false) { 
    /* ... */ 
  }
}

Car myCar = new Car();
myCar.Accelerate(55);

— ( , ). .

Generic co- and contravariance


. . .

Embedded interop types («NoPIA»)


, , — , . , COM , () MS Office, .

C# 5.0


Asynchronous methods


public async Task ReadFirstBytesAsync(string filePath1, string filePath2)
{
    using (FileStream fs1 = new FileStream(filePath1, FileMode.Open))
    using (FileStream fs2 = new FileStream(filePath2, FileMode.Open))
    {
        await fs1.ReadAsync(new byte[1], 0, 1); // 1
        await fs2.ReadAsync(new byte[1], 0, 1); // 2
    }
}

. , — (Async/await C#: ). (Await in catch/finally blocks) , (akka.net , ). - — . . , .

Caller info attributes


public void DoProcessing()
{
    TraceMessage("Something happened.");
}

public void TraceMessage(string message,
        [System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
        [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
        [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
    System.Diagnostics.Trace.WriteLine("message: " + message);
    System.Diagnostics.Trace.WriteLine("member name: " + memberName);
    System.Diagnostics.Trace.WriteLine("source file path: " + sourceFilePath);
    System.Diagnostics.Trace.WriteLine("source line number: " + sourceLineNumber);
}

// Sample Output:
//  message: Something happened.
//  member name: DoProcessing
//  source file path: c:\Users\username\Documents\Visual Studio 2012\Projects\CallerInfoCS\CallerInfoCS\Form1.cs
//  source line number: 31

, , . .

C# 6.0


Compiler-as-a-service (Roslyn)


( ) . , .

Import of static type members into namespace


using static System.Console;
using static System.Math;
using static System.DayOfWeek;
class Program
{
    static void Main()
    {
        WriteLine(Sqrt(3*3 + 4*4)); 
        WriteLine(Friday - Monday); 
    }
}

. , , . — . , . , Intellisense , . , , — .

Exception filters


try { … }
catch (MyException e) when (myfilter(e))
{
    …
}

. , ? , , ?

Await in catch/finally blocks


— .

Auto property initializers


public class Customer
{
    public string First { get; set; } = "Jane";
    public string Last { get; set; } = "Doe";
}

. , .

Default values for getter-only properties


public class Customer
{
    public string First { get; } = "Jane";
    public string Last { get; } = "Doe";
}

.

Expression-bodied members


public string Name => First + " " + Last;
public Customer this[long id] => store.LookupCustomer(id); 

, . , . — .

Null propagator (succinct null checking)


public static string Truncate(string value, int length)
{          
  return value?.Substring(0, Math.Min(value.Length, length));
}

. . , , , .

String Interpolation


! , -, . :

“Total lines: “ + totalLines + ”, total words: “ + totalWords + ”.”;


, ? , , 2 :


, Format(...) .
. , , C# :) !

nameof operator


if (x == null) throw new ArgumentNullException(nameof(x));
WriteLine(nameof(person.Address.ZipCode)); // prints "ZipCode"

“Caller info attributes”. .

Dictionary initializer


var numbers = new Dictionary<int, string> {
    [7] = "seven",
    [9] = "nine",
    [13] = "thirteen"
};

, , . . .

-
, . . , . , . , . -, . , . , — . , IDE — .

Java. ( )

, http- ( ) . , . , , , . , . , . . , .

, — . , ( — ) . , , , . , . — , .


C# 7.0 proposals


— , . . “ C# 7”, .

Binary literals


int x = 0b1010000; 
int SeventyFive = 0B10_01011;

, , , — . « » — ?

Local functions


public void Foo(int z)
{
    void Init()
    {
        Boo = z;
    }
    Init();
}

C# (Delphi), , . . , , C# — . . , , . , .

, — . , ( , , ), .

Tuples


, , / out-. .

Pattern matching, conditions in switch


// type pattern
public void Foo(object item)
{
    if (item is string s)
    {
        WriteLine(s.Length);
    }
}
// Var Pattern
public void Foo(object item)
{
    if(item is var x)
    {
        WriteLine(item == x); // prints true
    }
}
// Wildcard Pattern
public void Foo(object item)
{
    if(item is *)
    {
        WriteLine("Hi there"); //will be executed
    }
}

.
, , . , , . .

Ref locals and ref returns


static void Main()
{
    var arr = new[] { 1, 2, 3, 4 };
    ref int Get(int[] array, int index)=> ref array[index]; 
    ref int item = ref Get(arr, 1);
    WriteLine(item);
    item = 10;
    WriteLine(arr[1]);
    ReadLine();
}
// Will print
// 2
// 10

. .

“” “ ” 7- C#, .

, ?


, C# (7- , ) :

  1. - LINQ. fluent-.
  2. .
  3. Var. , .
  4. — .


:

  1. LINQ ( ).
  2. .
  3. , , .
  4. .
  5. Async/await.
  6. .

Source: https://habr.com/ru/post/302076/


All Articles