How to call constructor without new?

后端 未结 4 782
夕颜
夕颜 2021-01-20 17:50

i know that string is like a class, and when creating a new string the string itself doesnt owe the value but only the value\'s pointer. but when creating a string there is

相关标签:
4条回答
  • 2021-01-20 18:39

    You can use cast operator to implicitly:

        sealed class Student
        {
            public string Name
            {
                get;
                private set;
            }
    
            Student()
            {
            }
    
            public static implicit operator Student(string name)
            {
                return new Student
                {
                    Name = name
                };
            }
        }
    

    Then you can do Student student = "Sabrina";.

    0 讨论(0)
  • 2021-01-20 18:39

    The string "hello" in your code, in all cases, does not involve a call to a constructor. It is a constant value, created at compile time, such that all instances of the string "hello" are all the same object. Similarly, the integer 1 and decimal value 3.456, and any other "literal" value, are constants that exist before runtime, before the constructor code can have a chance to be called.

    The code new string("hello"); cannot be called, as there is no constructor for string that takes a string as a value. However, if you changed it to new string("hello".ToCharArray());, you would get a string object, but it won't be the same thing as the string "hello". You've actually created a new string, at a separate memory location, from just plain "hello". It only just so happens to have the same character values contained in it as "hello".

    The significance is that, if you do use the implicit type conversion trick, then one string literal converted to your type will not be the same object:

    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);
        }
    }
    

    In other words, a.Equals(b) returns false. In order to make the Equals method return true, you'll have to override the Equals method in your Foo class.

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

    But, as mentioned by other posters, this is an obfuscation. You'll make it difficult to use the code as well as difficult to debug it. It changes what looks like a regular assignment to a full method call. And it breaks many of the tools that Visual Studio provides for inspecting code, such as F12 to jump to a method definition.

    Implicit type conversion should be used only in cases where the two types are actually quite interchangeable in use, with minor differences in their functionality. The float type can implicitly convert to double because there are no extra methods and functions for double vs float, and increasing the precision from float to double does not change the value. However, going from double to float requires an explicit cast, because the loss of precision changes the value represented.

    0 讨论(0)
  • 2021-01-20 18:43

    You could have a method named createObject() and use that while having the constructors private, discourage their use.

    0 讨论(0)
  • 2021-01-20 18:54

    Although you can get this done using an implicit operator, I would highly recommend not doing this at all. Strings are special animals in C# and they get special treatment - along with other special classes like int and float, you can create them without explicitly newing them up due to the way the C# compiler works:

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

    However, this behavior is typically restricted to those special classes. Adding an implicit operator to do this is bad practice for multiple reasons:

    • It hides what is actually going on underneath. Are we creating a new Student under the hood when converting from a string?
    • It is unmaintainable. What happens when you have to add another parameter to the constructor to include the Student's ID number as well?
    • It eliminates the possibility of using implicitly-typed variables. You can't call var student = "name"; you must call Student student = "name".

    The implicit operator paradigm breaks down very quickly. Though it's a cool thing to do, you're setting yourself up for a bad time down the road and making your code more difficult to read. I would highly advise just using new Student("name") like all other normal objects in C#.

    0 讨论(0)
提交回复
热议问题