新的对象是否过时了?

时间:2010-01-08 17:25:53

标签: c# java language-design

好的,这就是问题......新关键字是否过时了?

考虑在C#(和java,我相信)有类型的严格规则。类是引用类型,只能在堆上创建。 POD类型在堆栈上创建;如果要在堆上分配它们,则必须将它们装入对象类型中。在C#中,structs是例外,它们可以在堆栈或堆上创建。

鉴于这些规则,我们是否还必须使用新关键字?根据类型使用适当的分配策略,语言是否有意义?

例如,我们目前必须写:

SomeClassType x = new SomeClassType();

而不是

SomeClassType x = SomeClassType();

甚至只是

SomeClassType x;

编译器将根据创建的类型是引用类型,继续并在堆上为x分配内存。

这适用于其他语言,如ruby,php等。 C / C ++允许程序员更好地控制创建对象的位置,因此有充分的理由要求使用new关键字。

new是否只是60年代和我们基于C的遗产的延续?

8 个答案:

答案 0 :(得分:18)

SomeClassType x = SomeClassType();

在这种情况下SomeClassType()可能是位于其他地方的方法,编译器如何知道是调用此方法还是创建新类。

SomeClassType x;

这不是很有用,大多数人都会像这样声明他们的变量,有时候他们需要时填充它们。因此,每次声明变量时在内存中创建实例都没有用。

答案 1 :(得分:16)

您的第三种方法不起作用,因为有时我们想要定义一种类型的对象并将其分配给另一种类型的变量。例如:

Stream strm = new NetworkStream();

我想要一个流类型(可能在某处传递),但在内部我想要一个NetworkStream类型。

我也多次在调用方法时创建一个新对象:

myobj.Foo(new NetworkStream());

这样做:

myobj.Foo(NetworkStream()); 

非常混乱。我是在创建一个对象,还是在我说NetworkStream()时调用一个方法?

答案 2 :(得分: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 };

Voilà,没有new的初始化。在这种情况下,编译器足够聪明,可以为您解决这个问题,因为您提供了一个定义整个对象的文字表达式。

所以我猜我的“回答”是,不要担心对象存在于记忆中的位置;使用new关键字,作为对象初始值设定项,用于需要初始化的对象。

答案 3 :(得分:5)

首先:

SomeClassType x;

未初始化,因此不应分配内存。

除此之外,如果有与该类名称相同的方法,如何避免出现问题。

假设你写了一些代码:

int World() { return 3; }

int hello = World();

一切都很好,快乐。

现在你稍后写一个新类:

class World 
{
    ...
}

突然,您的int hello = World()行不明确。

答案 4 :(得分:3)

出于性能原因,这可能是一个坏主意。例如,如果你想让x成为已经创建的对象的引用,那么创建一个新对象然后立即处理它就会浪费内存和处理器时间。

答案 5 :(得分:2)

  

这对它有意义吗?   语言使用正确的分配   策略基于类型?

这正是C#编译器/运行时已经完成的工作。 new关键字只是以任何对该对象有意义的方式构造对象的语法。

删除new关键字会使得调用构造函数变得不那么明显。对于类似的示例,请考虑out参数:

myDictionary.TryGetValue(key, out val);

编译器已经知道valout。如果你不这么说,它会抱怨。但它使代码更具可读性。

至少,这就是理由 - 在现代IDE中,除了实际插入的文本之外,还可以通过其他方式找到并突出显示这些内容。

  

新的只是60年代的延续   和我们的C基础传承?

绝对不是。 C没有new个关键字。

答案 6 :(得分:1)

我已经使用Java编程了很多年,我从不关心我的对象是在堆还是堆栈上。从那个角度来看,输入new或者不输入它是完全相同的。

我想这对其他语言更有意义。

我唯一关心的是班级有正确的操作,我的对象是正确创建的。

BTW,我使用(或尝试)只在工厂使用new关键字,所以我的客户端看起来像这样

SomeClasType x = SomeClasType.newInstance();

请参阅:Effective Java Item:1

答案 7 :(得分:0)

如果你没有无参数构造函数,这可能会变得很难看。

如果你有多个构造函数,这可能会变得非常难看。