2010-01-08 2 views
8

Итак, вот вопрос ... это новое ключевое слово устарело?Являются ли новые объекты устаревшими?

Рассмотрите в C# (и, я считаю, java) существуют строгие правила для типов. Классы являются ссылочными типами и могут создаваться только в куче. Типы POD создаются в стеке; если вы хотите выделить их в куче, вам нужно поместить их в тип объекта. Исключение составляют C12, structs, они могут быть созданы в стеке или в куче.

Учитывая эти правила, имеет ли смысл, что нам все еще нужно использовать новое ключевое слово? Не имеет ли смысл, чтобы язык использовал правильную стратегию распределения, основанную на типе?

К примеру, в настоящее время мы должны написать:

SomeClassType x = new SomeClassType(); 

вместо

SomeClassType x = SomeClassType(); 

или даже просто

SomeClassType x; 

компилятор, основанный на том, что тип создаваемого является ссылочным типом, вперед и выделяйте память для x в куче.

Это относится к другим языкам, таким как ruby, php, et al. C/C++ позволяют программисту больше контролировать, где создаются объекты, поэтому у него есть все основания требовать нового ключевого слова.

new просто переживание 60-х годов и наше наследие на основе C?

+0

И это не сообщество wiki, потому что ...? –

+0

Не знаю. Как вы думаете, это должно быть? –

+1

Это совершенно правильный вопрос. И хороший, тоже. Нет необходимости в CW. – bsneeze

ответ

18
SomeClassType x = SomeClassType(); 

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

SomeClassType x; 

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

+0

Верно, но не могли бы вы устранить это, установив его на нуль? –

+2

@flyfish: Нет, если вы хотите, чтобы это было неизменным (т.'final' в эквивалентах Java или других языков), так как тогда вы не могли назначить ему что-нибудь еще позже. –

+1

, если он устанавливает нуль, как он будет строить позже? –

5

Для начала:

SomeClassType x; 

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

Помимо этого, как избежать проблем, когда существует метод с тем же именем, что и класс.

Допустим, вы пишете код:

int World() { return 3; } 

int hello = World(); 

и все красиво и весел.

Теперь вы пишете позже новый класс:

class World 
{ 
    ... 
} 

Вдруг ваш int hello = World() линия неоднозначна.

+1

* Внезапно ваша строка int hello = World() неоднозначна. * Это не динамические языки (например, python) могут отлично справиться с этим сценарием, скомпилированный язык должен вызывать ошибку (точно так же, как при создании метода, который уже определен) – OscarRyz

+0

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

+0

@Stan, в моем примере World() - это просто функция, которая возвращает int, поэтому она абсолютно корректна. – tster

0

Если у вас нет конструктора без параметров, это может стать уродливым.

Если у вас есть несколько конструкторов, это может стать настоящим уродливым.

1

Я программировал на Java в течение нескольких лет, и мне никогда не волнует, находится ли мой объект в куче или стеке. С этой точки зрения мне все равно набрать new или не вводить его.

Я думаю, это было бы более актуальным для других языков.

Единственное, что меня волнует, - это класс, который имеет правильные операции, и мои объекты созданы правильно.

BTW, я использую (или попытаться) использовать new ключевое слово только на заводе merthod так что мой клиент выглядит так или иначе

SomeClasType x = SomeClasType.newInstance(); 

См: Effective Java Item:1

+1

Объекты Java никогда не находятся в стеке. – tster

+2

Фактически, виртуальная точка Hotspot может выделять объекты в стеке в качестве оптимизации, если после анализа escape он определяет, что он является локальным для метода. Точка зрения очень умна с такими вещами, хотя программисту никогда не придется заботиться. –

+1

@Joe M: Yeap, поэтому мы должны отметить конечные переменные, которые хотим получить из внутренних классов. Но это компилятор. – OscarRyz

16

Ваш третий метод не будет работать, так как иногда мы хотим определить объект одного типа и назначить его переменной другого типа. Например:

Stream strm = new NetworkStream(); 

Я хочу тип потока (возможно передать куда-нибудь), но внутренне я хочу тип NetworkStream.

Также много раз я создаю новый объект при вызове метода:

myobj.Foo(new NetworkStream()); 

делает, что таким образом:

myobj.Foo(NetworkStream()); 

очень запутанным. Я создаю объект или вызываю метод, когда говорю NetworkStream()?

+0

Хорошая точка. Я не собирался освещать все варианты использования здесь. Просто общий вопрос. –

+0

Какова цель этого? просто сделайте 'NetworkStream strm = new NetworkStream();' – tster

+0

Да, Stream strm = new NetworkStream() - плохой пример ... это, вероятно, лучший: Stream [] streams = new Stream [2]; streams [0] = новый NetworkStream(); streams [1] = новый FileStream(); Извините за дерьмовое форматирование, я не могу понять, как кодировать формат в этом поле комментариев. –

3

По соображениям производительности это может быть плохая идея. Например, если вы хотите, чтобы x была ссылкой для объекта, который уже был создан, было бы потерей памяти и времени процессора для создания нового объекта, а затем немедленно избавиться от него.

6

Если вы могли бы просто написать SomeClassType x; и автоматически инициализировать его, это не позволило бы конструкторам с любыми параметрами. Не каждый SomeClassType будет иметь конструктор без параметров; как компилятор узнает, какие аргументы поставлять?

public class Repository 
{ 
    private IDbConnection connection; 

    public Repository(IDbConnection connection) 
    { 
     if (connection == null) 
     { 
      throw new ArgumentNullException("connection"); 
     } 
     this.connection = connection; 
    } 
} 

Как бы создать экземпмент этого объекта всего лишь Repository rep;? Это требует, чтобы зависимый объект функционировал должным образом.

Не говоря уже, вы можете написать код, например, так:

Dictionary<int, SomeClass> instances = GetInstancesFromSomewhere(); 
SomeClass instance; 
if (instances.TryGetValue(1, out instance)) 
{ 
    // Do something 
} 

Вы действительно хотите автоматически инициализируется для вас?

Если вы только что написали SomeClassType x = SomeClassType(), то это не делает различия между конструктором и методом в области видимости.

В целом:

Я думаю, что есть фундаментальное непонимание того, что new ключевое слово для.Тот факт, что типы значений распределены по стеку, и «ссылочные» типы выделяются в куче, представляет собой деталь реализации. Ключевое слово new является частью спецификации . Как программист, вам все равно, выделено ли оно в кучу или стеке (большую часть времени), но вам нужно указать , как объект инициализируется.

Есть другие допустимые типы инициализаторах тоже, такие как:

int[] values = { 1, 2, 3, 4 }; 

вуаля, инициализации, без new. В этом случае компилятор был достаточно умен, чтобы понять это, потому что вы предоставили буквальное выражение, определяющее весь объект.

Таким образом, я думаю, что мой «ответ»: не беспокойтесь о том, где объект существует с точки зрения памяти; используйте ключевое слово new, как и предполагалось, как инициализатор объекта для объектов, требующих инициализации.

2

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

Это именно то, что уже делает компилятор/выполнение C#. Ключевое слово new - это просто синтаксис для построения объекта любым способом, который имеет смысл для этого объекта.

Удаление ключевого слова new сделает его менее очевидным, если вызывается конструктор. Для подобного примера рассмотрим out параметры:

myDictionary.TryGetValue(key, out val); 

компилятор уже знает, что val является out. Если вы этого не говорите, он жалуется. Но это делает код более удобочитаемым, чтобы заявить об этом.

По крайней мере, это оправдание - в современных IDE эти вещи могут быть найдены и выделены другими способами, помимо фактического вставленного текста.

Является ли новый прорыв с 60-х годов и нашим наследием на основе C?

Определенно нет. C не имеет ключевого слова new.

Смежные вопросы