C# к C#, функциям языка удобства

Я хотел бы изучить то, что является всеми удобными функциями C#, и как они отображаются на C#.

Например, автоматические свойства:

public string Foo { get; set; }

... карты к чему-то вроде этого:

string <Foo>k__BackingField;

[CompilerGenerated]
public string Foo {
   get { return this.<Foo>k__BackingField; } 
   set { this.<Foo>k__BackingField = value; } 
}

Циклы foreach:

foreach(char c in "Hello") {
   Console.WriteLine(c);
}

... карты к чему-то вроде этого (я думаю):

CharEnumerator en;

try {

   en = "Hello".GetEnumerator();

   while (en.MoveNext()) {
      char c = en.Current;

      Console.WriteLine(c);
   }

} finally {

   IDisposable disp = en as IDisposable;

   if (disp != null)
      disp.Dispose();
}

Избавление от перечислителя делает foreach очень полезный при контакте с неуправляемыми ресурсами, как цикличное выполнение через строки в файле или записи в базе данных.

Я думаю, что хорошее понимание этих функций высокого уровня может помочь нам написать лучший код. Каковы другие удобные функции C#, и как они отображаются на C#?

11
задан 2 revs, 2 users 95% 9 January 2010 в 22:18
поделиться

14 ответов

Если вы хотите поговорить о количестве сохраненного кода, то самыми большими сахарными запоминающими устройствами (IMO) являются те, которые вы используете:

итерационные блоки

Пример:

public static IEnumerable<int> Get() {yield return 1; yield return 2;}

сохранено:

  • написание IEnumerable реализации
  • написание IEnumerator реализации
  • состояния обработки регистратора; видели ли вы , насколько это ужасно? Серьёзно.

захваченные переменные (анонные методы / lambdas)

Пример:

var list2 = list1.FindAll(x => (x.Value % 10) == find);

сохранен:

  • написание класса для удержания состояния
    • в сложных случаях вложенное состояние
  • инициализирующее обертку состояния
  • пишущее метод на этом компиляторе

Expression lambda compiler

Пример (сверху):

Expression<Func<Foo,bool>> pred = x => (x.Value % 10) == find;

Сохранилось:

  • yeuch - много древовидного кода; очень, очень сложный; в вышеприведенном я вижу (не в определенном порядке) Expression. Parameter, Expression.Property, Expression.Field, Expression.Constant, Expression.Equal, Expression.Modulo, Expression.Lambda... combine ;-p
11
ответ дан 3 December 2019 в 01:00
поделиться

используется синтаксический сахар

using(x) 
{
    ...
}

Maps to

try {
    // Code
}
finally
{
    if(x != null)
        ((IDisposable)x).Dispose();
}

From- вещь в LINQ - синтаксический сахар

from x in l where y select z;

транслируется в

l.Where(x => y).Select(x => z);
8
ответ дан 3 December 2019 в 01:00
поделиться

Оператор ?: , который проверяет булевое или логическое выражение и возвращает первое значение, если тест возвращает true, и второе значение, если тест возвращает false:

условие ? first_expression : second_expression

Что по сути означает:

var x;
if (condition)
{
    x = first_expression;
}
else
{
    x = second_expression
}

Используя оператор ?:, можно записать int x = условие ? 10 : 20; вместо того, чтобы записывать целое оператор if.

4
ответ дан 3 December 2019 в 01:00
поделиться

Анонимные типы:

var message = new { Message = "Hello, world!", MessageID = 1 };

переведено на

<>f__AnonymousType0<string, int> message =
    new <>f__AnonymousType0<string, int>("Hello, world!", 1);

где

[CompilerGenerated]
[DebuggerDisplay(
    @"\{ Message = {Message},
    MessageID = {MessageID} }",
    Type="<Anonymous Type>"
 )
]
internal sealed class <>f__AnonymousType0<
    <Message>j__TPar,
    <MessageID>j__TPar
> {
    // Fields
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private readonly <Message>j__TPar <Message>i__Field;
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private readonly <MessageID>j__TPar <MessageID>i__Field;

    // Methods
    [DebuggerHidden]
    public <>f__AnonymousType0(
        <Message>j__TPar Message,
        <MessageID>j__TPar MessageID
    ) {
        this.<Message>i__Field = Message;
        this.<MessageID>i__Field = MessageID;
    }

    [DebuggerHidden]
    public override bool Equals(object value) {
        var type = value as <>f__AnonymousType0<
            <Message>j__TPar,
            <MessageID>j__TPar
        >;
        return (((type != null) && 
            EqualityComparer<<Message>j__TPar>.Default.Equals(
                this.<Message>i__Field, 
                type.<Message>i__Field)
            ) &&
            EqualityComparer<<MessageID>j__TPar>.Default.Equals(
                this.<MessageID>i__Field,
                type.<MessageID>i__Field)
            );
    }

    [DebuggerHidden]
    public override int GetHashCode() { 
        int num = 0x2e22c70c;
        num = (-1521134295 * num) +
            EqualityComparer<<Message>j__TPar>.Default.GetHashCode(
                this.<Message>i__Field
            );
        return ((-1521134295 * num) +
            EqualityComparer<<MessageID>j__TPar>.Default.GetHashCode(
                this.<MessageID>i__Field)
            );
    }

    [DebuggerHidden]
    public override string ToString() {
        StringBuilder builder = new StringBuilder();
        builder.Append("{ Message = ");
        builder.Append(this.<Message>i__Field);
        builder.Append(", MessageID = ");
        builder.Append(this.<MessageID>i__Field);
        builder.Append(" }");
        return builder.ToString();
    }

    // Properties
    public <Message>j__TPar Message {
        get {
            return this.<Message>i__Field;
        }
    }

    public <MessageID>j__TPar MessageID {
        get {
            return this.<MessageID>i__Field;
        }
    }
}
3
ответ дан 3 December 2019 в 01:00
поделиться

Выражения лямбды - еще один пример.

var myZombies = myMonsters.Where(monster => monster.Kind == MonsterKind.Zombie);

вытягивает делегата лямбда в свой собственный метод со странным названием.

Вы можете использовать рефлектор и переключаться между версиями на C# в диалоге опций, чтобы увидеть различия в том, как такие вещи будут разрешаться.

1
ответ дан 3 December 2019 в 01:00
поделиться

Методы расширения.

Если это метод расширения:

static class ObjectExtensions
{
    public void ExtensionMethod(this object obj)
    {
        // Do something here...
    }
}

И вы вызываете obj.ExtensionMethod()

Он преобразует в:

ObjectExtensions.ExtensionMethod(obj)

Если у вас случайно есть версия C# компилятора, поддерживающая методы расширения, вы можете обманом заставить компилятор разрешить использовать методы расширения в версиях .Net до 3. 5, создав System.Runtime.CompilerServices.ExtensionAttribute, вот так: (Это совершенно безопасно, так как компилятор отображает методы расширения в стандартную IL)

namespace System.Runtime.CompilerServices
{
    using System;

    internal sealed class ExtensionAttribute : Attribute
    {
    }
}
1
ответ дан 3 December 2019 в 01:00
поделиться

LINQ в целом (особенно с использованием синтаксиса запроса LINQ), по сути, является основным C # /. Чистая функция удобства, которая заменяет логику для петель / итераторов / комплексной логики.

6
ответ дан 3 December 2019 в 01:00
поделиться

Инициализации объекта являются довольно синтаксическим сахаром:

 public class Book
{
 public string Author { get; set; }
 public string Title { get; set; }
}

Book book = new Book() {Author = "John Smith", Title = "C# Syntax"};

Вышеупомянутый это еще один способ написать:

Book book = new Book();
book.Author = "John Smith";
book.Title = "C# Syntax";

Неявные типы:

var book = new Book() {Author = "John Smith", Title = "C# Syntax"};
3
ответ дан 3 December 2019 в 01:00
поделиться
  1. для , , в то время как , , ... в то время как , выключатель - противоречивый ответ :)

    Вы можете заменить его некоторым кодом, основанным на , если и GOTO .

  2. Блокировка () {} может быть переведено на Monitor.enter () и Monitor.exit () в TRY - наконец-то с проверкой нулевой проверки (см. . Это? )

5
ответ дан 3 December 2019 в 01:00
поделиться

Анонимные делегаты изменяются на методы во время компиляции, поэтому это:

var collection = new[] { 1, 2, 3, 4 }.Where(i => i == 2);

вызывает создание нового метода:

[CompilerGenerated]
private static bool <Main>b__0(int i)
{
    return (i == 2);
}

и изменения в:

IEnumerable<int> collection = new int[] { 1, 2, 3, 4 }.Where<int>(<Main>b__0);

обратите внимание, что он использует имя метода, которое вы не можете создать перед компиляцией <Главная> B__0 - Вы не можете иметь <> в имени метода, поэтому он всегда избегает столкновений.

Тот же процесс происходит с этим, а также I => I == 2 :

delegate(int i) { return i == 2; }

Вы также заметите, что вы можете использовать короткую руку для:

new[] { 1, 2, 3, 4 }
// goes to...
new int[] { 1, 2, 3, 4 }

и

var foo = new Foo();
// goes to...
Foo foo = new Foo();
3
ответ дан 3 December 2019 в 01:00
поделиться

Необычно среди языков высокого уровня, C # имеет оператор «goto», и, следовательно, несколько других операторов C # можно считать языковыми переводами в утверждение GOTO.

Например, оператор оператора IF () отображается непосредственно к GOTO, а стандарт для () LOOP на самом деле на самом деле отображается на карт () цикл, который отображает GOTO.

Заявление «Переключатель ()» необычно, поскольку он скомпилирован по-разному в зависимости от количества случаев и типа аргумента коммутатора. Таким образом, невозможно рассмотреть это языковое преобразование к GoTo.

0
ответ дан 3 December 2019 в 01:00
поделиться

Ваш вопрос не очень специфичен. Но, полагаю, вы имеете в виду что-то вроде «расстояния редактирования» между ними? То есть сколько нужно изменить s1, чтобы добраться до s2?

Посмотрите статью в Википедии на Изменить расстояние .

-121--4716653-

можно вычислить размер пересечения между каждым набором

-121--4716655-

Оператор объединения null (??) может быть довольно мелким. Это...

ISomeRef myRef = firstChoice ?? secondChoice ?? fallback;

Переводится в какую-то функциональность, эквивалентную:

ISomeRef myRef = firstChoice;
if(myRef == null) myRef = secondChoice;
if(myRef == null) myRef = fallback;

Я говорю функционально эквивалентную, потому что я еще не посмотрел в отражателе:)

3
ответ дан 3 December 2019 в 01:00
поделиться

Инициализирует сбор (и тип вывода):

var scoobies = new List<Scooby>()
        {
            new Scooby("Buffy"),
            new Scooby("Willow"),
            new Scooby("Xander")

        };

Карты к:

List<Scooby>() scoobies = new List<Scooby>();
scoobies.Add(new Scooby("Buffy"));
scoobies.Add(new Scooby("Willow"));
scoobies.Add(new Scooby("Xander"));
0
ответ дан 3 December 2019 в 01:00
поделиться

Solr пока не поддерживает обновление отдельных полей , но существует проблема JIRA об этом (почти 3 года на данный момент написания).

Пока это не реализовано, необходимо обновить весь документ.

UPDATE : начиная с Solr 4 + это реализовано, вот документация .

-121--239055-

Ваш вопрос не очень специфичен. Но, полагаю, вы имеете в виду что-то вроде «расстояния редактирования» между ними? То есть сколько нужно изменить s1, чтобы добраться до s2?

Посмотрите статью в Википедии на Изменить расстояние .

-121--4716653-

Значение < T > является еще одним невероятным удобством. Особенно удобен синтаксис ? , как в int? , сокращенно от Nullable < int > .

1
ответ дан 3 December 2019 в 01:00
поделиться