Comments 66
Добавлю от себя пару любопытных заметок:
- Поля, помеченные как
const
, объявлены в классе, однако используются только компилятором — во все места их использования он подставляет фактические значения, не генерируя код обращения к полю. Это не оптимизация — среда CLR запрещает обращаться к константным полям так же, как к обычным. - Если в метод передается анонимная функция вида
SomeMethod(x => OtherMethod(x))
, это можно переписать короче:SomeMethod(OtherMethod)
. string.Empty
нельзя использовать, например, в качестве значения для параметра по умолчанию — а литерал пустой строки можно.- Extension-методы можно в том числе вызывать как обычный статический метод, указывая имя класса и передавая объект явно в качестве первого параметра. Фактически они различаются только тем, что на методе и содержащем его классе ставится атрибут
ExtensionAttribute
, который подсказывает компилятору, что данный метод можно использовать как метод-расширение.
Ну это уже совсем очевидно, но на всякий случай поясню.
2. x => OtherMethod(x) это анонимная лямбда функция, причем в данном случае её сигнатура будет совпадать с методом OtherMetod (принимает такой же параметр x и возвращает результат OtherMetod). Т.к. кроме вызова OtherMethod она ничего не делает, мы просто выкидываем её, передавая вместо неё сам метод
3. Потому что параметр по умолчанию должен быть Compile Type Constant, а String.Empty это статическое поле класса.
4. Фактически это обычные статические методы статического класса, они не будут иметь каких-то привилегий в доступе к полям класса, в частности оттуда не не будут видны private и protected члены. Просто использование слова this добавляет «синтаксический сахар», позволяя вызывать их, записывая через точку от экземпляра, а не с помощью имени содержащего их класса.
5. ReSharper делает вашу жизнь проще, автоматически подчеркивая и исправляя ошибки, подобные описанной в пункте 2.
2. x => OtherMethod(x) это анонимная лямбда функция, причем в данном случае её сигнатура будет совпадать с методом OtherMetod (принимает такой же параметр x и возвращает результат OtherMetod). Т.к. кроме вызова OtherMethod она ничего не делает, мы просто выкидываем её, передавая вместо неё сам метод
3. Потому что параметр по умолчанию должен быть Compile Type Constant, а String.Empty это статическое поле класса.
4. Фактически это обычные статические методы статического класса, они не будут иметь каких-то привилегий в доступе к полям класса, в частности оттуда не не будут видны private и protected члены. Просто использование слова this добавляет «синтаксический сахар», позволяя вызывать их, записывая через точку от экземпляра, а не с помощью имени содержащего их класса.
5. ReSharper делает вашу жизнь проще, автоматически подчеркивая и исправляя ошибки, подобные описанной в пункте 2.
Пункт 3 также связан с пунктом 1: например, использовать
int.MaxValue
вполне можно. Почему string.Empty
не сделали таким же константным полем, непонятно — ведь в MSIL есть инструкция для загрузки строки, аналогичная инструкции для загрузки числа.Вот комментарий к данному полю.
// The Empty constant holds the empty string value.
//We need to call the String constructor so that the compiler doesn't mark this as a literal.
//Marking this as a literal would mean that it doesn't show up as a field which we can access from native.
public static readonly String Empty = "";
Это сделано для доступа к полю из неуправляемого(native) кода.
// The Empty constant holds the empty string value.
//We need to call the String constructor so that the compiler doesn't mark this as a literal.
//Marking this as a literal would mean that it doesn't show up as a field which we can access from native.
public static readonly String Empty = "";
Это сделано для доступа к полю из неуправляемого(native) кода.
Вы серьезно были удивлены вас этим, особенно (1)?
Автор конечно погреет свое самолюбие на почве того, как много людей оказались невежественней. Но все равно спасибо, я для себя действительно что-то открыл, чтение было полезным. На редкость.
От себя:
Методы расширения имеют небольшую особенность на фоне обычных методов — мы можем обращаться к методам, даже если объекты существуют как null, в то время как обычный метод в классе при таком выпадает. Проще говоря мы не можем создать рабочий метод в классе аля IsNull() { return a == null; }, в то время как метод расширения будет так работать. Например именно поэтому оно и работает
От себя:
Методы расширения имеют небольшую особенность на фоне обычных методов — мы можем обращаться к методам, даже если объекты существуют как null, в то время как обычный метод в классе при таком выпадает. Проще говоря мы не можем создать рабочий метод в классе аля IsNull() { return a == null; }, в то время как метод расширения будет так работать. Например именно поэтому оно и работает
Это потому, что метод-расширение, преобразуется при компиляции в вызов соотв. статического метода из класса.
т.е. есть расширение
public static class Ext
{
public static bool Check(this object o)
{
return o == null;
}
}
Его вызов:
if(o.Check())
{
//do something
}
при компиляции преобразуется в
if(Ext.Check(o))
{
//do something
}
т.е. есть расширение
public static class Ext
{
public static bool Check(this object o)
{
return o == null;
}
}
Его вызов:
if(o.Check())
{
//do something
}
при компиляции преобразуется в
if(Ext.Check(o))
{
//do something
}
Почему вы пишите «Поля, помеченные как const»? Поля это поля. Константы это константы. У них разные реализации и назначение.
С точки зрения CLR «константа» — это не отдельная сущность, а поле с выставленным флагом
Можете убедиться в этом с помощью Reflection:
IsLiteral
.Можете убедиться в этом с помощью Reflection:
typeof(int).GetField("MaxValue")
Поля, помеченные как const, объявлены в классе, однако используются только компилятором — во все места их использования он подставляет фактические значения, не генерируя код обращения к полю.
Этот факт становится важным только при декомпиляции — использования константных полей пропадают из кода. В остальных случаях — бесполезная информация.
Если в метод передается анонимная функция вида SomeMethod(x => OtherMethod(x)), это можно переписать короче: SomeMethod(OtherMethod)
Extension-методы можно в том числе вызывать как обычный статический метод, указывая имя класса и передавая объект явно в качестве первого параметра.
На такие советы хочется сказать только одно: поставьте, наконец, решарпер.
string.Empty нельзя использовать, например, в качестве значения для параметра по умолчанию — а литерал пустой строки можно.
Не вижу смысла выделять ошибки компиляции в советы. Такие ошибки допускаются один раз, всегда обнаруживаются, тривиально исправляются. Та же претензия к некоторым пунктам статьи.
Мой комментарий и не претендовал на раскрытие сакральных знаний, которые облегчат жизнь всем пишущим на C#. Я просто перечислил несколько неочевидных для меня вещей в языке \ платформе, некоторые из которых действительно подсказал решарпер.
Автор оригинального топика (Damien Guard) всё-таки преследовал какие-то практические цели: научить полезному, помочь избежать ошибок. Зачем топик превращают в сборник забавных фактов о языке — мне не понять. В моём представлении подсказки, которые даются стандартными инструментами разработки, нет смысла выносить в топик. С таким же успехом можно пройтись по списку ошибок и предупреждений компилятора и инструментов статического анализа кода — советов наберутся тысячи.
Если в метод передается анонимная функция вида SomeMethod(x => OtherMethod(x)), это можно переписать короче: SomeMethod(OtherMethod).
Это можно назвать η-conversion.
Поля, помеченные как const, объявлены в классе, однако используются только компилятором
В частности, это значит, что если некоторая константа была выставлена наружу как const field, то её изменение требует перекомпиляции не только используемой сборки, но и использующей (т.е. ломающее изменение). Предоставление property такого недостатка лишено.
Фактически они различаются только тем, что на методе и содержащем его классе ставится атрибут ExtensionAttribute, который подсказывает компилятору, что данный метод можно использовать как метод-расширение.
Проще говоря, extension-методы — это не фича, это сахар.
12. Структуры являются неизменяемыми, когда используются в коллекциях
Дело не колеекциях, а в том, что list[0] вернет rvalue. можете поэксперементировать с обычным методом, возвращающим структуру.
Дело не колеекциях, а в том, что list[0] вернет rvalue. можете поэксперементировать с обычным методом, возвращающим структуру.
Ну, так там и написано: «В первом случае мы получим ошибку компиляции, поскольку индексатор коллекции это всего-навсего метод, который возвращает копию нашей структуры. Во втором случае мы ошибки не получим, поскольку индексация в массивах это не вызов метода, а обращение именно к нужному элементу.»
Как-то неоднозначно получилось) В общем, и ваш и его ответ, видимо, лучше просто объединить, для полной ясности, что-то вроде «поскольку индексатор коллекции это всего-навсего метод, а методы возвращают структуры в виде типа значения (в отличие от классов, возвращаемых в виде ссылочного типа), возвращаемый результат изменить невозможно...»…
В первом случае мы получим ошибку компиляции, поскольку индексатор коллекции это всего-навсего метод, который возвращает копию нашей структуры. Во втором случае мы ошибки не получим, поскольку индексация в массивах это не вызов метода, а обращение именно к нужному элементу.Обращение будет к копии экземпляра типа значения, а не к самому экземпляру.
using System;
namespace Tst
{
struct Node
{
public int Value;
}
class Program
{
static void Main()
{
var node = new Node {Value = 1};
var array = new[] {node};
array[0].Value = 2;
Console.WriteLine(node.Value); // Выведет 1
Console.ReadKey();
}
}
}
9. Вы не можете использовать константу с именем value__ в перечисленииАналогично нельзя использовать методы T get_XXX() и void set_XXX(T) внутри класса, если объявлено свойство T XXX {get; set;}
public class Node
{
public int Value { get; set; }
public int get_Value() // error: member with the same
// signature is already declared
{
return 1;
}
public void set_Value(int value) // error: member with the same
// signature is already declared
{
}
}
5. Перечисления могут иметь методы расширенияБолее того, даже примитивные типы могут иметь методы расширения.
Кстати, если кому-то до сих пор требуется писать под второй фреймворк, то для использования методов расширения достаточно добавить в любой из проектов всего 4 строчку:
namespace System.Runtime.CompilerServices {
public class ExtensionAttribute : Attribute {}
}
Иными словами, методы расширения — это полностью фича языка, а не среды исполнения.
Насколько я понимаю, такого понятия как «Private переменная экземпляра класса» просто не существует, есть просто «Private переменная класса» (по крайней мере в С++ так). Поэтому ничего удивительного в данном примере нет.
Не совсем. Сама переменная все равно является сущностью экземпляра, а не класса, а вот уровень доступа к ней действительно ограничен классом, а не экземпляром.
Кстати, отмечу тринадцатый факт, потому что, видимо, все так погрузились в обсуждение деталей статьи, что не заметили его.
Факт 13: В статье под названием «8 фактов, которые вы, возможно, не знали о C#» описаны 12 фактов. Ой, теперь уже 13.
Факт 13: В статье под названием «8 фактов, которые вы, возможно, не знали о C#» описаны 12 фактов. Ой, теперь уже 13.
Ну а что вас удивляет? Автор же честно пишет, что «8 фактов (..) вы, возможно, не знали», то есть исходит из того, что минимум 4 факта в статье знает уж точно каждый хабровчанин.
В некотором роде откровением для меня стало лишь наплевательство компилятора на несоблюдение типов инициализируемых полей в случае рекурсивного вызова конструкторов. Но, для иллюстрации применимости этих знаний на практике могу процитировать классика:
Шерлок Холмс: Коперник — знакомая фамилия. Что он сделал?
Доктор Ватсон: Боже мой, так ведь это же он открыл, что Земля вращается вокруг Солнца! Или этот факт вам тоже неизвестен?
Шерлок Холмс: Но мои глаза говорят мне, что скорее Солнце вращается вокруг Земли. Впрочем, может быть, он и прав, ваш этот… как его — Коперник.
Доктор Ватсон: Простите меня, Холмс! Но вы же человек острого ума, это сразу видно! …Как же вы не знаете вещей, которые известны каждому школьнику?!
Шерлок Холмс: Ну, когда я был школьником, я это знал, а потом основательно забыл.
Доктор Ватсон: Вы что, хвастаетесь своим невежеством?! …Но ведь я говорю об элементарных вещах, которые знает каждый!
Шерлок Холмс: Но я-то не каждый, Ватсон, поймите: человеческий мозг — это пустой чердак, куда можно набить всё, что угодно. Дурак так и делает: тащит туда нужное и ненужное. И наконец наступает момент, когда самую необходимую вещь туда уже не запихнёшь. Или она запрятана так далеко, что ее не достанешь. Я же делаю всё по-другому. В моём чердаке только необходимые мне инструменты. Их много, но они в идеальном порядке и всегда под рукой. А лишнего хлама мне не нужно.
Доктор Ватсон: Учение Коперника, по-вашему, хлам?!
Шерлок Холмс: Хорошо. Допустим, Земля вращается вокруг Солнца.
Доктор Ватсон: То есть… то есть… ка́к — допустим?!
Шерлок Холмс: Земля вращается вокруг Солнца. Но мне в моём деле это не пригодится!
Кстати, правда некоторым колет глаза, вон, какие-то редиски меня уже за карму покусали.
Шерлок Холмс: Коперник — знакомая фамилия. Что он сделал?
Доктор Ватсон: Боже мой, так ведь это же он открыл, что Земля вращается вокруг Солнца! Или этот факт вам тоже неизвестен?
Шерлок Холмс: Но мои глаза говорят мне, что скорее Солнце вращается вокруг Земли. Впрочем, может быть, он и прав, ваш этот… как его — Коперник.
Доктор Ватсон: Простите меня, Холмс! Но вы же человек острого ума, это сразу видно! …Как же вы не знаете вещей, которые известны каждому школьнику?!
Шерлок Холмс: Ну, когда я был школьником, я это знал, а потом основательно забыл.
Доктор Ватсон: Вы что, хвастаетесь своим невежеством?! …Но ведь я говорю об элементарных вещах, которые знает каждый!
Шерлок Холмс: Но я-то не каждый, Ватсон, поймите: человеческий мозг — это пустой чердак, куда можно набить всё, что угодно. Дурак так и делает: тащит туда нужное и ненужное. И наконец наступает момент, когда самую необходимую вещь туда уже не запихнёшь. Или она запрятана так далеко, что ее не достанешь. Я же делаю всё по-другому. В моём чердаке только необходимые мне инструменты. Их много, но они в идеальном порядке и всегда под рукой. А лишнего хлама мне не нужно.
Доктор Ватсон: Учение Коперника, по-вашему, хлам?!
Шерлок Холмс: Хорошо. Допустим, Земля вращается вокруг Солнца.
Доктор Ватсон: То есть… то есть… ка́к — допустим?!
Шерлок Холмс: Земля вращается вокруг Солнца. Но мне в моём деле это не пригодится!
Кстати, правда некоторым колет глаза, вон, какие-то редиски меня уже за карму покусали.
Просто менять оригинальное название статьи нехорошо))) А фактов и впрямь 12)
Я думаю перечисления — зло
1. Перечисления повышают безопасность использования типов. Например, при определении константных значений для Interop, предпочтительнее воспользоваться enum, а не множеством из const-членов.
2. Предпочту switch там, где нет необходимости во всяких паттернах типа «стратегии».
3. Флаговые перечисления бывают катастрофически полезными.
Сомневаюсь, что я привёл полный список аргументов «за» использование перечислений.
О каком зле вообще можно говорить, если в самом .NET 100500 перечислений, и с каждой версией их становится всё больше?
Не зря же авторы шарпа вернули в язык плюсовые перечисления, когда придумывали свою джаву с блэкджеком и шлюхами.
Не зря же авторы шарпа вернули в язык плюсовые перечисления, когда придумывали свою джаву с блэкджеком и шлюхами.
Не знаю, откуда берутся такие космические числа в опросе. В топике либо капитанство (первые 8 вопросов), либо совершенно бесполезная информация (большинство последующих). Если в опросе участвовали те, кто реально разрабатывает на шарпе, то это очень печально. :(
Что оно поддерживается — это логичная фича. Почему не поддерживать, если можно передавать несколько аргументов?
Вы забыли рассказать, что интернирование ещё и настраивается, то есть ваше утверждение верно только в условиях по умолчанию.
Это, конечно, любопытная информация, но у любого нормально разраба стоит решарпер, и он будет ругаться. И это верно только для переменных, там по сути код вставляется в конструктор как есть. Константы компилятор разрулит.
И это сообщается тем, кто думает, что строковые константы создаются каждый раз? :)) Там же много букв.
Забавный факт. Но бесполезный на 100%.
Ваш пример можно объянить безо всяких махинаций. Функции безусловно вызывают друг друга — переполнение стека. Соответственно, опять бесполезная информация.
Если это не знаешь, то обнаруживаешь при первой попытке использовать. Смысл запоминать отдельно?
А здесь ещё и безграмотное объяснение. Впрочем, здесь опять ошибка компиляции, то есть, если не знаешь, то придётся узнать, когда понадобится.
1. Индексаторы могут использовать params параметры
Что оно поддерживается — это логичная фича. Почему не поддерживать, если можно передавать несколько аргументов?
2. Строковые литералы, определенные в вашем коде хранятся в единственном экземпляре
Вы забыли рассказать, что интернирование ещё и настраивается, то есть ваше утверждение верно только в условиях по умолчанию.
6. Порядок, в котором вы описываете статические переменные, имеет значение
Это, конечно, любопытная информация, но у любого нормально разраба стоит решарпер, и он будет ругаться. И это верно только для переменных, там по сути код вставляется в конструктор как есть. Константы компилятор разрулит.
8.Спецификация языка C# уже на вашем компьютере
И это сообщается тем, кто думает, что строковые константы создаются каждый раз? :)) Там же много букв.
9. Вы не можете использовать константу с именем value__ в перечислении
Забавный факт. Но бесполезный на 100%.
10. Инициализатор полей позволяет слишком много
Ваш пример можно объянить безо всяких махинаций. Функции безусловно вызывают друг друга — переполнение стека. Соответственно, опять бесполезная информация.
11. Вы можете использовать только C# синонимы при описании базового типа перечисления
Если это не знаешь, то обнаруживаешь при первой попытке использовать. Смысл запоминать отдельно?
12. Структуры являются неизменяемыми, когда используются в коллекциях
А здесь ещё и безграмотное объяснение. Впрочем, здесь опять ошибка компиляции, то есть, если не знаешь, то придётся узнать, когда понадобится.
Согласен на все 100%.
Первый пример тоже бесполезен, как по мне. Я хоть и знаю о такой возможности, но не стал бы использовать такое в своем коде — индексаторы с несколькими параметрами существуют не для таких хаков, код теряет наглядность. Если вы встречаете в коде O[1,2] — это что — попытка получить 1 элемент из двумерного массива или первый и второй элемент из одномерного? Гарантирую, что подавляющее большинство проголосует за двумерный массив.
Читая пункт 5 о том, что перечисления могут иметь методы расширения, испытывал смешанные чувства. Мало того, что КО, так еще и описано настолько узко, что новичка, не ведающего о существовании расширений это только запутает.
Первый пример тоже бесполезен, как по мне. Я хоть и знаю о такой возможности, но не стал бы использовать такое в своем коде — индексаторы с несколькими параметрами существуют не для таких хаков, код теряет наглядность. Если вы встречаете в коде O[1,2] — это что — попытка получить 1 элемент из двумерного массива или первый и второй элемент из одномерного? Гарантирую, что подавляющее большинство проголосует за двумерный массив.
Читая пункт 5 о том, что перечисления могут иметь методы расширения, испытывал смешанные чувства. Мало того, что КО, так еще и описано настолько узко, что новичка, не ведающего о существовании расширений это только запутает.
Ай, промазал уровнем.
Абсолютно согласен.
Есть редкие и полезные факты. А в этой статье почти всё — редкие и бесполезные факты.
1. 95% программистов НИКОГДА не воспользуются этим видом индексатора. Вообще никогда.
2. Тоже самое хотел сказать. Интернирование настраиваемо. И, кстати, надо разобраться, там, по-моему в разных версиях .NET, настройки по умолчанию разные.
9. Также согласен. Бесполезный факт на 100%.
10. За такие вызовы вообще сразу ссаной тряпкой по морде надо бить.
Вот такие «обнаружатели интересных фактов» потом мучают джуниоров, а то и мидлов на собеседованиях всяким бредом.
Абсолютно согласен.
Есть редкие и полезные факты. А в этой статье почти всё — редкие и бесполезные факты.
1. 95% программистов НИКОГДА не воспользуются этим видом индексатора. Вообще никогда.
2. Тоже самое хотел сказать. Интернирование настраиваемо. И, кстати, надо разобраться, там, по-моему в разных версиях .NET, настройки по умолчанию разные.
9. Также согласен. Бесполезный факт на 100%.
10. За такие вызовы вообще сразу ссаной тряпкой по морде надо бить.
Вот такие «обнаружатели интересных фактов» потом мучают джуниоров, а то и мидлов на собеседованиях всяким бредом.
Конечно. Но в статье не про кишки, а про безголовость.
Кстати, чтобы быть хорошим разрабом, не надо знать кишки платформы.
Любой разраб, столкнувшись с непонятным поведением, может прогуглить это поведение.
Для хорошего разработчика, который лабает на C++, Haskell, C#.NET, F#.NET всю эту бредятину запомнить невозможно. Лучше Кнута почитать.
Я ни раз видел в подкастах как тот же Roy Osherove натыкается на непонятку и просто гуглит её.
Кстати, чтобы быть хорошим разрабом, не надо знать кишки платформы.
Любой разраб, столкнувшись с непонятным поведением, может прогуглить это поведение.
Для хорошего разработчика, который лабает на C++, Haskell, C#.NET, F#.NET всю эту бредятину запомнить невозможно. Лучше Кнута почитать.
Я ни раз видел в подкастах как тот же Roy Osherove натыкается на непонятку и просто гуглит её.
Причём ж тут бесполезная/небесполезная? Тут описывается, как можно делать, а не как нужно.
О некоторых пунктах я не знал, например, просто потому, что никогда не использовал и даже не задумывался использовать в реальном коде.
Да и вообще, не стоит так нагло выпячивать своё ЧСВ. Я как бы ещё с 2004 года зарабатываю на C# но вопросы 1, 8, 9, 10 у меня не стояли ни разу. А, следовательно, точного ответа я не знал. И что тут печального?
О некоторых пунктах я не знал, например, просто потому, что никогда не использовал и даже не задумывался использовать в реальном коде.
Да и вообще, не стоит так нагло выпячивать своё ЧСВ. Я как бы ещё с 2004 года зарабатываю на C# но вопросы 1, 8, 9, 10 у меня не стояли ни разу. А, следовательно, точного ответа я не знал. И что тут печального?
О некоторых пунктах я не знал, например, просто потому, что никогда не использовал и даже не задумывался использовать в реальном коде.
И никогда не задумаетесь использовать. ;) О том, собственно, и речь.
Бесполезная информация забывается. Вы завтра же забудете про это всё, потому что применить невозможно.
Периодически заглядываю в тему на stackoverflow под названием скрытые фичи c#, фактически сборник удобных фишек с индексатором в первом сообщении. Периодически, потому что за один раз сложно всё попробовать и принять.
В индексе клик на название ссылается на MSDN, клик на автора — на его сообщение, часто с примером.
В индексе клик на название ссылается на MSDN, клик на автора — на его сообщение, часто с примером.
Что ж, в этом вопросе после капитанства идёт хоть что-то полезное:
После 5 страниц утомился…
When debugging, you can type $exception in the Watch\QuickWatch\Immediate window and get all the info on the exception of the current frame. This is very useful if you've got 1st chance exceptions turned on!
string s = string.Format("{0:positive;negative;zero}", i);
RealProxy lets you create your own proxies for existing types
Programmers moving from C/C++ may miss this one:
In C#, % (modulus operator) works on floats!
The extern alias keyword to reference two versions of assemblies that have the same fully-qualified type names.
После 5 страниц утомился…
А знаете ли вы, что при компиляции каждой сборки, в неё «втихую» добавляется особенный класс с зарезервированным именем "<Module>"? В него по идее должны добавляться глобальные функции и константы, которые в C# не поддерживаются. А особенный он потому, что он вообще не имеет базового класса, то есть не наследуется от System.Object. Ещё одним примером класса-сироты является… Правильно, сам System.Object =)
Зачем вы во втором пункте про строковые литералы используете в примере метод String.IsInterned()?
Как по мне, так это только запутает читателя, ведь действие этого метода нужна пояснять на другом примере.
Так же String переопределяет оператор == и он сравнивает не по ссылкам а по значению. (Determines whether two specified strings have the same value.)
А в вашем случае надо использовать простую проверку
Как по мне, так это только запутает читателя, ведь действие этого метода нужна пояснять на другом примере.
Так же String переопределяет оператор == и он сравнивает не по ссылкам а по значению. (Determines whether two specified strings have the same value.)
А в вашем случае надо использовать простую проверку
Object.ReferenceEquals("what", "wh" + "at")
[Conditional(«DEBUG»)] применимо только к классам и методам, в отличие от #if DEBUG.
В блоге Эрика Липперта этих фактов на целую книгу наберется. Например про строки и транзитивность ==.
Добавлю свои 5 копеек.
Код ниже компилируется (пример от Джона Скита):
Инициализаторы без new:
Код ниже компилируется (пример от Джона Скита):
static void Main()
{
var foo = "foo";
foo = 5;
}
// ...
class var
{
public static implicit operator var(string x)
{
return null;
}
public static implicit operator var(int x)
{
return null;
}
}
Инициализаторы без new:
class Foo
{
public Bar Bar;
}
class Bar
{
public int Value;
}
static void Main()
{
var foo = new Foo() {Bar = {Value = 5}};
}
Иногда, а особенно после таких статей, завидую «шарперам» белой завистью. Эх, хоть бейте меня ногами… Не удержусь. В Java бы хоть немножко такого… Даже о value-types не мечтаю, но вот хотя бы unsigned…
А зачем value-types в Java? Содержимое «не убегающего» объекта умеет размещаться в стеке, при этом совершенно прозрачно. Ну разве что в массивы объекты как value-types не положить — это так критично?
Вопрос без подвоха — я пишу на C# и считал это такой уж киллерфичей языка.
Вот функциональность крайне полезно, но под java можно либо надеяться на восьмую версию либо осваивать scala.
Вопрос без подвоха — я пишу на C# и считал это такой уж киллерфичей языка.
Вот функциональность крайне полезно, но под java можно либо надеяться на восьмую версию либо осваивать scala.
С использованием value-types улучшается memory reference locality. Если объект собран из нескольких value-объектов, он лежит в памяти одним отрезком и с большой вероятностью прогрузится в кеш-строку при обращении к любому полю. Если объекты-компоненты доступны по ссылкам, обращение к очередному компоненту — прогрузка новой кеш-строки, сотни тактов процессорного времени.
А unsigned-то зачем нужен?
Всё это конечно интересно, но вопрос на сколько это может быть полезным!
А за код в пункте 10, надо давать 10 суток.
А за код в пункте 10, надо давать 10 суток.
Все это интересно, но все это описывал Рихтер в 3-м издании. Не заметить было трудно, потому как шло под выделенным жирным «Примечание».
Sign up to leave a comment.
8 фактов, которые вы, возможно, не знали о C#