如何在没有新的情况下调用构造函数

时间:2013-09-02 17:18:00

标签: c# constructor

我知道字符串就像一个类,当创建一个新字符串时,字符串本身并不是值,而只是值的指针。但是在创建字符串时,不需要使用new;

string a = "hello";

而不是

string a = new string("hello");

我知道第二种选择也是可能的,但我想了解的是为什么第一种选择?

假设我有一个班级学生,他的构造函数得到string。要创建一个新类,我必须使用保存的单词new。

student example = new student("Sabrina");

我尝试过载oparator =,但这是不可能的。

如何创建像string这样的新类(不使用单词new)?

student example = "Sabrina"; 

4 个答案:

答案 0 :(得分:9)

您可以隐式使用强制转换运算符:

    sealed class Student
    {
        public string Name
        {
            get;
            private set;
        }

        Student()
        {
        }

        public static implicit operator Student(string name)
        {
            return new Student
            {
                Name = name
            };
        }
    }

然后你可以Student student = "Sabrina";

答案 1 :(得分:6)

在所有情况下,代码中的字符串"hello"都不涉及对构造函数的调用。它是在编译时创建的常量值,这样字符串"hello"的所有实例都是相同的对象。类似地,整数1和十进制值3.456以及任何其他“文字”值是在运行时之前存在的常量,在构造函数代码有机会被调用之前。

无法调用代码new string("hello");,因为没有字符串构造函数将字符串作为值。但是,如果将其更改为new string("hello".ToCharArray());,则会得到一个字符串对象,但它与字符串"hello"不同。实际上,您已经在一个单独的内存位置创建了一个新字符串,而不仅仅是普通的"hello"。它恰好恰好包含在"hello"中的相同字符值。

重要的是,如果你使用隐式类型转换技巧,那么转换为你的类型的一个字符串文字将不是同一个对象:

class Foo
{
    private string value;
    public Foo(string val)
    {
        this.value = val;
    }
    public static implicit operator Foo(string value)
    {
        return new Foo(value);
    }
}

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        Foo a = "asdf";
        Foo b = "asdf";
        Assert.AreNotEqual(a, b);
    }
}

换句话说,a.Equals(b)返回false。为了使Equals方法返回true,您必须覆盖Foo类中的Equals方法。

public override bool Equals(object obj)
{
    return obj is Foo && value.Equals(((Foo)obj).value);
}

但是,正如其他海报所提到的,这是一种混淆。您将难以使用代码以及难以调试它。它改变了对完整方法调用的常规赋值。它打破了Visual Studio为检查代码提供的许多工具,例如F12以跳转到方法定义。

只有在两种类型在使用中实际上可以互换的情况下才应使用隐式类型转换,但功能上的细微差别。 float类型可以隐式转换为double,因为double vs float没有额外的方法和函数,并且将精度从float提高到{{} 1}}不会更改值。但是,从doubledouble需要显式强制转换,因为精度损失会更改所代表的值。

答案 2 :(得分:6)

虽然可以使用implicit operator完成此操作,但我强烈建议您不要这样做。 Strings是C#中的特殊动物,它们会得到特殊处理 - 与intfloat等其他特殊类一起,您可以创建它们而不会明确new C#编译器的工作方式:

var myInt = 0;
var myFloat = 0f;
var myString = "string";

但是,此行为通常仅限于那些特殊类。由于多种原因,添加implicit operator来执行此操作是不好的做法:

  • 它会隐藏下面的实际内容。我们是否在从new Student转换时创建了string
  • 无法维护。当你必须在构造函数中添加另一个参数以包含Student的ID号时会发生什么?
  • 它消除了使用隐式类型变量的可能性。您无法调用var student = "name";您必须致电Student student = "name"

implicit operator范例很快崩溃了。虽然这是一件很酷的事情,但是你要在艰难的时刻为自己做好准备,让你的代码更难以阅读。我强烈建议像使用C#中的所有其他普通对象一样使用new Student("name")

答案 3 :(得分:0)

你可以有一个名为createObject()的方法,并在将构造函数设为私有时使用它,不鼓励使用它们。