views:

395

answers:

8

Ok, so here's the question... is the new keyword obsolete?

Consider in C# (and java, I believe) there are strict rules for types. Classes are reference types and can only be created on the heap. POD types are created on the stack; if you want to allocate them on the heap you have to box them in an object type. In C#, structs are the exception, they can be created on the stack or heap.

Given these rules, does it make sense that we still have to use the new keyword? Wouldn't it make sense for the language to use the proper allocation strategy based on the type?

For example, we currently have to write:

SomeClassType x = new SomeClassType();

instead of

SomeClassType x = SomeClassType();

or even just

SomeClassType x;

The compiler would, based on that the type being created is a reference type, go ahead and allocate the memory for x on the heap.

This applies to other languages like ruby, php, et al. C/C++ allow the programmer more control over where objects are created, so it has good reason to require the new keyword.

Is new just a holdover from the 60's and our C based heritage?

+17  A: 
SomeClassType x = SomeClassType();

in this case SomeClassType() might be a method located somewhere else, how would the compiler know whether to call this method or create a new class.

SomeClassType x;

This is not very useful, most people declare their variables like this and sometimes populate them later when they need to. So it wouldn't be useful to create an instance in memory each time you declare a variable.

Stan R.
True, but couldn't you address this by setting it to null?
Jeff Paquette
@flyfish: Not if you wanted it to be immutable (i.e. `final` in Java or other languages' equivalents), as then you couldn't assign anything else to it later.
Andrzej Doyle
if he sets to null how he will construct later?
Daniel Moura
I'm not that familiar with the ins and outs of java and final. If you have an object marked final, but is not assigned to, can you assign to it later?
Jeff Paquette
@flyfishr64, wouldn't setting it to null look something like this `SomeClassType x = null;` so when I finally want to set it to a class, how would that look??
Stan R.
@stan R Why wouldn't it look like a normal assignment? `x = SomeClassType(params);`
Jeff Paquette
your first argument against it is invalid. just because it "looks like a method" doesn't mean it can't construct a class. there's no reason that has to be a constructor invocation or just the invocation of a method that returns an instance of SomeClassType (perhaps from searching through a global list or something). The "magic" of the new operator can be encapsulated in a special property of the constructor function.
rmeador
@rmeador,in that case what would happen if i had a class named `SomeClassType` and a method that said `DerivedSomeClassType SomeClassType()`, which class are you really initializing then?
Stan R.
@Stan: I'm afraid I don't understand...
rmeador
+3  A: 

For starters:

SomeClassType x;

is not initialized so no memory should be allocated.

Other than that, how do you avoid problems where there is a method with the same name as the class.

Say you write some code:

int World() { return 3; }

int hello = World();

and everything is nice and jolly.

Now you write a new Class later:

class World 
{
    ...
}

Suddenly your int hello = World() line is ambiguous.

tster
*Suddenly your int hello = World() line is ambiguous.* It is not dynamic languages ( like python ) can handle this scenario very well, a compiled language should throw an error ( just like when you create a method that's already defined )
OscarRyz
Given the power of reflection, I don't think this is an issue. C# can determine the difference between a type and an instance of the type with the same name (even though it's not a good thing to do!). Though it would be easy for the compiler to raise a diagnostic in this case
Jeff Paquette
@Stan, in my example World() is just a function which returns an int, so it is perfectly valid.
tster
@tster, you're right my mistake. This is a prime example of why it would not be a good idea.
Stan R.
A: 

If you don't have a parameterless constructor, this could get ugly.

If you have multiple constructors, this could get real ugly.

Austin Salonen
+1  A: 

I've been programming with Java for a number of years and I have never care if my object is on the heap or the stack. From that perspective is all the same to me to type new or don't type it.

I guess this would be more relevant for other languages.

The only thing I care is the class have the right operations and my objects are created properly.

BTW, I use ( or try ) to use the new keyword only in the factory merthod so my client looks like this anyway

SomeClasType x = SomeClasType.newInstance();

See: Effective Java Item:1

OscarRyz
Java objects are never on the stack.
tster
Actually, the Hotspot VM can allocate objects on the stack as an optimization if, after escape analysis, it determines it is local to a method. Hotspot is very intelligent with such things, though the programmer should never really have to care.
Joe M
@Joe M: Yeap, that's why we have to mark as final variables we want to access from inner classes. But that's the compiler job.
OscarRyz
@Oscar: That suddenly makes sense to me. I never made the connection between final and allocation. My comment was in reply to tster, btw.
Joe M
@Joe M: I know!, actually I was supporting you :)... ohh written conversations need some smileys to work properly ;)
OscarRyz
+14  A: 

Your third method will not work, since sometimes we want to define a object of one type and assign it to a variable of another type. For instance:

Stream strm = new NetworkStream();

I want a stream type (perhaps to pass on somewhere), but internally I want a NetworkStream type.

Also many times I create a new object while calling a method:

myobj.Foo(new NetworkStream());

doing that this way:

myobj.Foo(NetworkStream()); 

is very confusing. Am I creating an object, or calling a method when I say NetworkStream()?

Timothy Baldridge
Good point. I wasn't attempting to cover all use cases here. Just a general question.
Jeff Paquette
what is the purpose of this? just do `NetworkStream strm = new NetworkStream();`
tster
Yeah, the Stream strm = new NetworkStream() is a bad example...this is probably a better one:Stream[] streams = new Stream[2];streams[0] = new NetworkStream();streams[1] = new FileStream();Sorry for the crappy formatting, I can't figure out how to code format in this comment box.
Timothy Baldridge
this is a good point as well..something I always use is `TextReader reader = new StringReader();`, which wouldn't be possible with the OP's propsed 3rd way.
Stan R.
@tster: the point is to make the rest of your code flexible by enforcing that it not depend on functionality specific to NetworkStream. You could of course type it as NetworkStream and just be careful to only use functionality provided by Stream in your code, but this way you get help from the compiler in doing so.
rmeador
If I am calling a constructor I know I have lost flexibility in that method. If I need flexibility I add a factory method or something to call the constructors for me. This argument doesn't apply if you keep your methods short and sweet.
tster
+2  A: 

For performance reasons, this might be a bad idea. For instance, if you wanted to have x be a reference for an object that's already been created, it would be a waste of memory and processor time to create a new object then immediately dispose of it.

ristonj
+4  A: 

If you could just write SomeClassType x; and have it automatically initialized, that wouldn't allow for constructors with any parameters. Not every SomeClassType will have a parameterless constructor; how would the compiler know what arguments to supply?

public class Repository
{
    private IDbConnection connection;

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

How would you instantiate this object with just Repository rep;? It requires a dependent object to function properly.

Not to mention, you might want to write code like so:

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

Would you really want it auto-initializing for you?

If you just wrote SomeClassType x = SomeClassType() then this makes no distinction between a constructor and a method in scope.

More generally:

I think there's a fundamental misunderstanding of what the new keyword is for. The fact that value types are allocated on the stack and "reference" types are allocated on the heap is an implementation detail. The new keyword is part of the specification. As a programmer, you don't care whether or not it's allocated on the heap or stack (most of the time), but you do need to specify how the object gets initialized.

There are other valid types of initializers too, such as:

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

Voilà, an initialization with no new. In this case the compiler was smart enough to figure it out for you because you provided a literal expression that defines the entire object.

So I guess my "answer" is, don't worry about where the object exists memory-wise; use the new keyword as it's intended, as an object initializer for objects that require initialization.

Aaronaught
+2  A: 

Wouldn't it make sense for the language to use the proper allocation strategy based on the type?

That's exactly what the C# compiler/runtime already does. The new keyword is just the syntax for constructing an object in whatever way makes sense for that object.

Removing the new keyword would make it less obvious that a constructor is being called. For a similar example, consider out parameters:

myDictionary.TryGetValue(key, out val);

The compiler already knows that val is an out. If you don't say so, it complains. But it makes the code more readable to have it stated.

At least, that is the justification - in modern IDEs these things could be found and highlighted in other ways besides actual inserted text.

Is new just a holdover from the 60's and our C based heritage?

Definitely not. C doesn't have a new keyword.

Daniel Earwicker