4

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

string a = "hello";

并不是

string a = new string("hello");

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

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

student example = new student("Sabrina");

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

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

student example = "Sabrina"; 
4

4 回答 4

10

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

    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";

于 2013-09-02T17:22:04.287 回答
6

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

new string("hello");无法调用该代码,因为没有将字符串作为值的字符串构造函数。但是,如果您将其更改为new string("hello".ToCharArray());,您将获得一个字符串对象,但它与字符串不同"hello"。您实际上已经在一个单独的内存位置创建了一个新字符串,来自 plain "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类型可以隐式转换为,因为vsdouble没有额外的方法和函数,并且从to增加精度不会改变值。但是,从to需要显式转换,因为精度的损失会改变表示的值。doublefloatfloatdoubledoublefloat

于 2013-09-02T17:34:08.117 回答
6

尽管您可以使用 来完成此操作implicit operator,但我强烈建议您根本不要这样做。Strings是 C# 中的特殊动物,它们得到特殊处理 - 与其他特殊类(如intand )一起,由于 C# 编译器的工作方式float,您可以在不显式创建它们的情况下创建它们:new

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

但是,此行为通常仅限于那些特殊类。添加一个implicit operator这样做是不好的做法,原因有很多:

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

implicit operator范式很快就崩溃了。虽然这是一件很酷的事情,但你会让自己陷入一段糟糕的时光,并使你的代码更难阅读。我强烈建议new Student("name")像 C# 中的所有其他普通对象一样使用。

于 2013-09-02T17:35:01.337 回答
0

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

于 2013-09-02T18:18:18.680 回答