带表达式的对象初始化器

时间:2019-01-04 10:59:42

标签: c#

是否可以像这样初始化一个对象?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApp3
{
    class Student
    {
        public bool IsStudent { get; set; }
        public int Age { get; set; }
        public string Name { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            /*
            ************Concise but not complied***********
            var student = GetDefault()
            {
                Age = 18,
                Name = "Nick"
            };
            */

            var student = GetDefault();
            student.Age = 18;
            student.Name = "Nick";


            Student GetDefault()
            {
                var stu = new Student()
                {
                    IsStudent = true
                };

                return stu;
            }
        }
    }
}

我认为是反复出现的“学生”。是多余的。

我想说的是可能的C#语法糖,而不是对象初始化解决方案。Student的属性可能很多。

如果不可能,请告诉我们可能的设计原因。

3 个答案:

答案 0 :(得分:2)

我同意HimBromBeere的声明。如果您真的希望语法与您所描述的相近,则可以执行以下操作。话虽如此,很明显,这现在改变了方法的含义,并且在我看来,这并不是一个很好的“样式”……但是它确实实现了一种与您所要求的语法接近的语法:

public class Student
{
    public bool IsStudent { get; set; }
    public int Age { get; set; }
    public string Name { get; set; }
}

public static void Main(string[] args)
{
    Student GetDefault(params Action<Student>[] modifiers)
    {
        var stu = new Student
        {
            IsStudent = true
        };

        if (modifiers != null)
        {
            foreach (var modifier in modifiers)
            {
                modifier(stu);
            }
        }

        return stu;
    }

    var student = GetDefault(
        s => s.Age = 18,
        s => s.Name = "Nick"
    );
}

答案 1 :(得分:1)

您应该尝试这样的事情:

using System;

namespace Problem
{
    public class Student
    {
        public bool IsStudent { get; set; }
        public int? Age { get; set; }
        public string Name { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            // GetDefault.
            Student Student_One = GetDefault();
            Console.WriteLine("IsStudent = {0} \nName = {1} \nAge = {2}", Student_One.IsStudent, Student_One.Age, Student_One.Name);

            Console.WriteLine("-------------------------");

            Student Student_Two = GetDefault();
            Student_Two.Age = 19;
            Student_Two.Name = "Nick";
            Console.WriteLine("IsStudent = {0} \nName = {1} \nAge = {2}", Student_Two.IsStudent, Student_Two.Age, Student_Two.Name);

            Console.WriteLine("-------------------------");

            Student Student_Three = new Student
            {
                IsStudent = true,
                Age = 20,
                Name = "Johnson"
            };
            Console.WriteLine("Name = {0} & Age = {1}" , Student_Three.Age,  Student_Three.Name);
            Console.WriteLine();
        }

        static Student GetDefault()
        {
            Student student = new Student
            {
                IsStudent = true
            };

            return student;
        }
    }
}

输出:

enter image description here

答案 2 :(得分:0)

您的假设(虽然可以理解)是错误的。 student.不是多余的。

想象一下有人会打电话给GetDefault 而没有,将其结果赋给一个变量-完全有效。

GetDefault()
{
   ...
}

GetDefault返回一个实例,您随后可以对其属性进行修改。但是,由于您没有将此对象分配给任何变量,因此将很快对其进行垃圾回收。因此,当您设置属性时,它根本不会具有任何效果,因为没有代码可以读取。特别是,您无法在该实例上调用DoSomethingWithUpdatedValues,因为该实例丢失了。

要避免的语法是实现此目的的唯一有效语法。您当然可以在方法中添加参数,但是会更改方法用途

我认为最干净的解决方案是让构造函数接受两个参数。实际上,对于完全没有名称或年龄的Student,您可以做的事情不多,因此只需将其提供给构造函数即可。