Являются ли новые объекты устаревшими? - PullRequest
8 голосов
/ 08 января 2010

Хорошо, вот вопрос ... новое ключевое слово устарело?

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

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

Например, нам сейчас нужно написать:

SomeClassType x = new SomeClassType();

вместо

SomeClassType x = SomeClassType();

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

SomeClassType x;

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

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

Является ли new пережитком 60-х годов и нашего наследия на основе Си?

Ответы [ 8 ]

18 голосов
/ 08 января 2010
SomeClassType x = SomeClassType();

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

SomeClassType x;

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

16 голосов
/ 08 января 2010

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

Stream strm = new NetworkStream();

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

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

myobj.Foo(new NetworkStream());

делает это так:

myobj.Foo(NetworkStream()); 

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

6 голосов
/ 08 января 2010

Если бы вы могли просто написать 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 по назначению, в качестве инициализатора объекта для объектов, требующих инициализации.

5 голосов
/ 08 января 2010

Для начала:

SomeClassType x;

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

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

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

int World() { return 3; }

int hello = World();

и все хорошо и весело.

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

class World 
{
    ...
}

Внезапно ваша int hello = World() линия становится неоднозначной.

3 голосов
/ 08 января 2010

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

2 голосов
/ 08 января 2010

Разве это не имеет смысла для язык, чтобы использовать правильное распределение стратегия на основе типа?

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

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

myDictionary.TryGetValue(key, out val);

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

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

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

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

1 голос
/ 08 января 2010

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

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

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

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

SomeClasType x = SomeClasType.newInstance();

См .: Эффективный элемент Java: 1

0 голосов
/ 08 января 2010

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

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

...