Я хотел бы изучить то, что является всеми удобными функциями 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#?
Если вы хотите поговорить о количестве сохраненного кода, то самыми большими сахарными запоминающими устройствами (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;
Сохранилось:
Expression. Parameter
, Expression.Property
, Expression.Field
, Expression.Constant
, Expression.Equal
, Expression.Modulo
, Expression.Lambda
... combine ;-pиспользуется синтаксический сахар
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);
Оператор ?: , который проверяет булевое или логическое выражение и возвращает первое значение, если тест возвращает true
, и второе значение, если тест возвращает false
:
условие ? first_expression : second_expression
Что по сути означает:
var x;
if (condition)
{
x = first_expression;
}
else
{
x = second_expression
}
Используя оператор ?:, можно записать int x = условие ? 10 : 20;
вместо того, чтобы записывать целое оператор if
.
Анонимные типы:
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;
}
}
}
Выражения лямбды - еще один пример.
var myZombies = myMonsters.Where(monster => monster.Kind == MonsterKind.Zombie);
вытягивает делегата лямбда в свой собственный метод со странным названием.
Вы можете использовать рефлектор и переключаться между версиями на C# в диалоге опций, чтобы увидеть различия в том, как такие вещи будут разрешаться.
Методы расширения.
Если это метод расширения:
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
{
}
}
LINQ в целом (особенно с использованием синтаксиса запроса LINQ), по сути, является основным C # /. Чистая функция удобства, которая заменяет логику для петель / итераторов / комплексной логики.
Инициализации объекта являются довольно синтаксическим сахаром:
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"};
для
, , в то время как
, ,
... в то время как
, выключатель
- противоречивый ответ :)
Вы можете заменить его некоторым кодом, основанным на , если
и GOTO
.
Блокировка () {}
может быть переведено на Monitor.enter () и Monitor.exit () в TRY - наконец-то с проверкой нулевой проверки (см. . Это? )
Анонимные делегаты изменяются на методы во время компиляции, поэтому это:
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();
Необычно среди языков высокого уровня, C # имеет оператор «goto», и, следовательно, несколько других операторов C # можно считать языковыми переводами в утверждение GOTO.
Например, оператор оператора IF () отображается непосредственно к GOTO, а стандарт для () LOOP на самом деле на самом деле отображается на карт () цикл, который отображает GOTO.
Заявление «Переключатель ()» необычно, поскольку он скомпилирован по-разному в зависимости от количества случаев и типа аргумента коммутатора. Таким образом, невозможно рассмотреть это языковое преобразование к GoTo.
Ваш вопрос не очень специфичен. Но, полагаю, вы имеете в виду что-то вроде «расстояния редактирования» между ними? То есть сколько нужно изменить 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;
Я говорю функционально эквивалентную, потому что я еще не посмотрел в отражателе:)
Инициализирует сбор (и тип вывода):
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"));
Solr пока не поддерживает обновление отдельных полей , но существует проблема JIRA об этом (почти 3 года на данный момент написания).
Пока это не реализовано, необходимо обновить весь документ.
UPDATE : начиная с Solr 4 + это реализовано, вот документация .
-121--239055-Ваш вопрос не очень специфичен. Но, полагаю, вы имеете в виду что-то вроде «расстояния редактирования» между ними? То есть сколько нужно изменить s1, чтобы добраться до s2?
Посмотрите статью в Википедии на Изменить расстояние .
-121--4716653- Значение < T >
является еще одним невероятным удобством. Особенно удобен синтаксис ?
, как в int?
, сокращенно от Nullable < int >
.