Каковы преимущества и недостатки вывода типов в C#?

У меня есть коллега, который против вывода типов в C#. Я полагаю, что большинство его аргументов были связаны с отсутствием удобочитаемости. Мой аргумент против этого заключается в том, что функции IntelliSense Visual Studio обеспечивают простой способ просмотра типов, и чтение их из кода не так необходимо, как могло бы быть, если бы мы писали код из блокнота.

Однако мне любопытны преимущества и недостатки использования вывода типов в C#. Я родом из С++ и знаю, что «авто» в С++ 0x имеет более объективное преимущество, поскольку вы не всегда знаете, какие типы вы получаете (особенно при программировании тяжелых шаблонов). В качестве примера можно использовать auto для сохранения значения Boost.Bind.

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

Lazy<List<MyNamespace.ISomeVeryLongInterfaceType>> myVar = obj.GetLazy();

это было бы:

var myVar = obj.GetLazy();

На мой взгляд, это намного чище. Однако есть ли объективные аргументы в пользу ИЛИ против вывода типов? Является ли это хорошей практикой программирования, даже в ситуациях, когда можно утверждать, что это не дает никакой пользы (например, использование «var» вместо «int»)?

Некоторая помощь в понимании того, как я должен использовать 'var' в своем повседневном кодировании, была бы здоровой.


person void.pointer    schedule 16.05.2011    source источник
comment
ReSharper, кажется, советует мне часто использовать var...   -  person NickAldwin    schedule 16.05.2011
comment
См. блоги. .msdn.com/b/ericlippert/archive/2011/04/20/   -  person Jon Skeet    schedule 16.05.2011
comment
Что ж, если вы спросите меня, явное наименование типа должно быть очень редким исключением, и даже в этом случае вы должны использовать наиболее общий тип, который вы можете позволить себе использовать здесь. Но опять же, я программирую в основном на Python (утиная типизация) и очень люблю Haskell (вывод типов) и структурную типизацию.   -  person    schedule 16.05.2011
comment
Меня забавляет, как всякий раз, когда возникают подобные обсуждения, примеры неизменно заполнены бесполезными именами, такими как myVar и obj.GetLazy(). Все кажется плохой идеей, когда вы называете переменные так хорошо.   -  person Dennis Zickefoose    schedule 16.05.2011


Ответы (6)


Вывод типа был изобретен именно по той причине, которую вы указали для С++, вы можете создавать анонимные типы, которые НЕ ИМЕЮТ имени типа (см., в частности, Lambdas и Linq).

Так что в таком случае это необходимо.

В другом случае (когда имя типа известно) дело сводится к стилю. Я использую var, когда тип действительно очевиден:

// I like this - less duplication and easier to read
var item = new List<ComplexObjectItem>();

вместо:

List<ComplexObjectItem> item = new List<ComplexObjectItem>();

Потому что это уменьшает дублирование.

Однако я предпочитаю не использовать его, если тип не сразу очевиден для читателя:

// I don't like this - I need to look up what the type is
var item = ResultOfSomeFunctionWhereICantSeeWhatItIs();

Но ваш пробег может отличаться.

person Jackson Pope    schedule 16.05.2011

Думаю, здравый смысл диктует следующие неформальные правила:

Если есть какое-то длинное имя, например:

Lazy<List<MyNamespace.ISomeVeryLongInterfaceType>> myVar = new Lazy<List<MyNamespace.ISomeVeryLongInterfaceType>>();

затем заменив его на

var myVar = new Lazy<List<MyNamespace.ISomeVeryLongInterfaceType>>();

имеет смысл, потому что вы все еще можете сказать, что это за объект.

Что-то двусмысленное, с другой стороны, может потребовать не использовать var:

Lazy<List<MyNamespace.ISomeVeryLongInterfaceType>> myVar = doProcess();
person NickAldwin    schedule 16.05.2011

Неявная типизация может быть полезна в одних случаях и вредна в других. Эрик Липперт недавно опубликовал статью на Использование и неправильное использование неявной типизации, которую стоит прочитать.

Следует помнить одну вещь: var предназначен только для пользователя, компилятор преобразует его в конкретное представление при компиляции.

Единственным недостатком является использование интерфейсов из класса.

предполагая, что GetCurrentList() возвращает IList<string>:

IEnumerable<string> list = GetCurrentList();

и

var list = GetCurrentList();

не такие, как во втором примере, список будет IList<string>.

Я склонен использовать явную типизацию и обычно использую var только тогда, когда это поможет улучшить читаемость кода и при использовании анонимных типов (потому что в этот момент вы должны это сделать).

person Joshua    schedule 16.05.2011

Мне нравится использовать определение типа, чтобы сделать код более кратким, однако я использую его только тогда, когда вижу, какой это тип в той же строке, например:

var myClass = new MyClass();

НО

MyClass myClass = RandomFuncThatGetsObject();

Я думаю, что использование var в первом примере не влияет на удобочитаемость, на самом деле это делает его более читаемым, однако использование var во втором примере ДОЛЖНО повлиять на читаемость.

person jcvandan    schedule 16.05.2011

Вывод типа необходим при работе с анонимными типами:

var x = new { Greeting = "Hello", Name = "World" };

Когда вы используете запросы LINQ, вы обычно постоянно используете анонимные типы.

person Antoine Aubry    schedule 16.05.2011

var myVar = obj.GetLazy();

Такой вывод типов, при наличии intellisense, является примерно хорошей идеей или хорошо. Однако, если бы не было intellisense, то я бы не считал это хорошей идеей. Вместо этого это был бы кошмар. Я полагаю, что без intellisense большинству разработчиков это не понравится из-за неудобств, вызванных отсутствием intellisense (и точного типа, и того, и другого).

Однако даже без intellisense было бы хорошо следующее:

var obj = new Lazy<List<MyNamespace.ISomeVeryLongInterfaceType>();

В таких ситуациях выведение типов является облегчением, так как позволяет избежать большого количества ввода и дублирования ввода!

С intellisense или без него я предпочитаю писать:

Lazy<List<MyNamespace.ISomeVeryLongInterfaceType> obj= obj.GetLazy();
person Nawaz    schedule 16.05.2011
comment
Даже с intellisense неясно, какой тип здесь извлекается, конечно, лучше, если кто-то может взглянуть на код и узнать, что происходит, если в таком методе 10 строк кода, вам придется пройти и навести над каждым объектом / вставайте intellisense для каждой строки, где это происходит — я бы разозлился, если бы мне пришлось это делать - person jcvandan; 16.05.2011