【问题标题】:Making methods that interact with instances of their structs制作与其结构实例交互的方法
【发布时间】:2018-02-08 16:18:26
【问题描述】:

我们在课堂上检查了结构,我们的任务是在结构内创建一个方法,该方法可以改变一个实例的字段与另一个实例的字段。例如,如果另一个人是经理,则更改一个人的名字。

struct Employee 
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string FullName
    {
        get => FirstName + LastName;
    }
    public int Age { get; set; }
    public string Role { get; set; }
    public double Salary { get; set; }
    public bool IsManager { get; set; }

    public static void EditInfo(ref Employee e1, ref Employee e2)
    {
        if (e1.IsManager)
        {
            Console.WriteLine($"Feel free to set {e2.FirstName}'s info: ");
            e2.FirstName = Console.ReadLine();
            e2.LastName = Console.ReadLine();
            Console.WriteLine($"From now on thy name is {e2.FullName}!");
        }
        else if (e2.IsManager)
        {
            Console.WriteLine($"Feel free to set {e1.FirstName}'s info: ");
            e1.FirstName = Console.ReadLine();
            e1.LastName = Console.ReadLine();
            Console.WriteLine($"From now on thy name is {e1.FullName}!");
        }
    }
}

现在,我有一种直觉,我的创作很糟糕。我完全不确定如何实际处理这个问题,对于实际的业务应用程序来说,这似乎是一个有价值的教训。我将不胜感激所有必要的技巧和窍门,以使这些与结构的多个实例交互的方法更好。

【问题讨论】:

  • “对于真正的业务应用来说,这似乎是一堂很有价值的课”——不,您几乎应该永远从使用可变结构开始。看起来你的代码满足了分配,但在几乎所有现实生活中,结构都应该是不可变的。
  • @JonSkeet 我相信这个任务更适合类,但我们还没有,甚至没有通过 OOP 概念,只是一个介绍。我可以欣赏编写良好的代码,而我的,就目前而言,不是。它显然不灵活,而且有点重复......
  • 当你被要求编写根本上存在问题的代码时——而且任务听起来就是这样——那么我就不会太担心了。听起来你也没有得到太多关于代码应该做什么的指导......我可能会将代码更改为不对称(有一个“应该”作为经理的参数,被选中)和另一个是有条件地被改变的,但仅此而已。
  • @JonSkeet 例如,如果我想遍历所有字段并更改它们而无需编写一百行长的方法...
  • 那么这几乎肯定也是一件坏事:)(你可以用反射来做,但用结构会更难......)

标签: c# struct properties multiple-instances interaction


【解决方案1】:

编辑:澄清

首先你应该使可变属性private set;,构造函数接受初始状态,并使EditInfo成为一个实例方法。这或多或少将每个Employee 视为具有访问控制的数据库记录,从而创建更简单的关系。

public class Employee
{
    public Employee(string firstName, string lastName, bool isManager, ...)
    {
        FirstName = firstName;
        LastName = lastName;
        IsManager = isManager;
        // remaining properties...
    }

    public string FirstName { get; private set; }
    public string LastName { get; private set; }
    public bool IsManager { get; private set; }
    // remaining properties...

    public void Edit(Employee requester)
    {
        if (requester.IsManager) {
            // query input from the user, make changes, and notify the user.
        } else {
            // notify the user that he doesn't have permission to edit this employee. 
        }
    }
}

因此使用它变成:

var manager = new Employee("Your", "Boss", isManager: true);
var sheep = new Employee("John", "Doe", isManager: false);

sheep.Edit(manager); // Essentially says "edit sheep using manager as permission".

其次,除非你的导师禁止你使用class,否则你应该把它变成一个类并去掉所有的ref 声明。 structref 在适当的情况下非常有用,但除非你意识到权衡和严格的代码,否则很容易引入一个很难考虑你的经验水平的错误。

类不会自动复制或需要ref 关键字。另一方面,结构确实会在没有ref 的情况下进行复制,因此在对其进行修改的每个调用站点上语义上都需要(但不强制)它。这具有您可能不知道的进一步含义。考虑属性。属性不能与 ref 一起传递,只能通过局部变量、字段和数组元素传递。不幸的是,这意味着目前无法通过 ref 传递结构属性(尽管在未来的 C# 版本中可能会发生变化)。这很可能会让你陷入困境。

总而言之,除非您有充分的理由使用结构(即 GC 性能、非常特殊用途的类型),否则更喜欢 C# 中的类。最重要的是,以可读性为目标。

【讨论】:

    猜你喜欢
    • 2020-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多