【问题标题】:Comparing two object state,before and after update比较两个对象状态,更新前后
【发布时间】:2010-01-28 13:33:41
【问题描述】:

第一件事。 我有以下课程:

class Employee
{
    private int employeeID;
    private string firstName;
    private string lastName;
    private bool eligibleOT;
    private int positionID;
    private string positionName;
    private ArrayList arrPhone;
    public IList<Sector> ArrSector {get; private set;}

    //the constructor method takes in all the information of the employee
    public Employee(int empID, string fname, string lname, bool elOT, int pos, string posname)
    {
        employeeID = empID;
        firstName = fname;
        lastName = lname;
        eligibleOT = elOT;
        positionID = pos;
        positionName = posname;
        arrPhone = new ArrayList();
        ArrSector = new List<Sector>();
    }

    //the constructor method takes in the employee id, the first name and the last name of the employee
    public Employee(int empid, string firstname,string lastname)
    {
        employeeID = empid;
        firstName = firstname;
        lastName = lastname;
    }

    //overtides the first name and the last name as a string.
    public override string ToString()
    {
        return firstName +" "+lastName;
    }



    public int EmployeeID
    {
        get { return employeeID; }
        set { employeeID = value; }
    }

    public string FirstName
    {
        get { return firstName; }
        set { firstName = value; }
    }

    public string LastName
    {
        get { return lastName; }
        set { lastName = value; }
    }

    public bool EligibleOT
    {
        get { return eligibleOT; }
        set { eligibleOT = value; }
    }

    public int PositionID
    {
        get { return positionID; }
        set { positionID = value; }
    }

    public string PositionName
    {
        get { return positionName; }
        set { positionName = value; }
    }

    public ArrayList ArrPhone
    {
        get { return arrPhone; }
        set { arrPhone = value; }
    }



    // The function assigns all the variables associated to the employee to a new object.
    public static object DeepClone(object obj)
    {
        object objResult = null;
        using (MemoryStream ms = new MemoryStream())
        {
            BinaryFormatter bf = new BinaryFormatter();
            bf.Serialize(ms, obj);
            ms.Position = 0;
            objResult = bf.Deserialize(ms);
        }
        return objResult;
    }

   //Memento pattern is used to save the employee state.
   //The changes will be rolled back if the update button not clicked
    public class Memento : IMemento
    {
        private Employee originator = null;
        private int employeeID;
        private string firstName;
        private string lastName;
        private bool eligibleOT;
        private int positionID;
        private string positionName;
        private ArrayList arrPhone;
        private IList<Sector> arrSector;

        public Memento(Employee data)
        {
            this.employeeID = data.EmployeeID;
            this.firstName = data.FirstName;
            this.lastName = data.LastName;
            this.eligibleOT = data.EligibleOT;
            this.positionID = data.PositionID;
            this.positionName = data.PositionName;
            this.arrPhone = data.ArrPhone;

            this.originator = data;
            this.arrSector = Extensions.Clone<Sector>(data.ArrSector);
        }

}

我在 winforms 中使用升 C。我的应用程序的前端在左侧有一个列表框,其中包含员工的名字。在左侧,有不同的文本框对应于列表框中选择的员工。我已经对其进行了编码,每次选择员工时,其属性(如员工 ID、姓名、职位等)都会显示在这些字段中。

如果用户更改员工的任何属性,他必须单击更新按钮才能对数据库进行更改。 现在真正的问题是,当用户更改所选员工的任何字段并选择另一个员工而不单击更新按钮时,我想显示一个弹出框告诉用户如果他选择另一个员工,所有更改都将是丢了。

出于这个原因,我创建了 momento 类来保存员工的先前状态。 我也尝试过重载 == 运算符

        public static bool operator ==(Employee e, Memento m)
        {
            return ((e.employeeID == m.employeeID) &&
               (e.firstName == m.firstName) &&
               e.lastName == m.lastName &&
               e.eligibleOT == m.eligibleOT &&
               e.positionID == m.positionID &&
               e.positionName == m.positionName &&
               e.arrPhone == m.arrPhone &&
               e.ArrSector == m.arrSector);
        }

        public static bool operator !=(Employee e, Memento m)
        {
            return (e.employeeID != m.employeeID);
        }

我的想法是比较这两个对象... 但我不成功。我该怎么做??如果进行了更改,我如何显示弹出窗口。?我在哪里放置代码以显示弹出窗口?

【问题讨论】:

    标签: c# .net-3.5 class memento


    【解决方案1】:

    提醒一句...在==!= 运算符中使用不同的逻辑通常不是一个好主意。能够同时拥有==!=false 有点不直观。

    if(!(a == b) && !(a != b))
    {
        // head explodes
    }
    

    除此之外,我猜您的比较代码中的Employee 类被引用为object(或其他父类)。也许是这样的:

    if(listBox1.SelectedItem != currentMemento)
    {
        ...
    }
    

    如果是这种情况,则编译器不会将 != 绑定到您的自定义实现。将 listBox1.SelectedItem 转换为 Employee 以强制执行此操作。

    if((Employee)listBox1.SelectedItem != currentMemento)
    {
        ...
    }
    

    但是,您可以采取许多其他方法来解决此问题:

    • 完全在 GUI 端实现实施,当文本字段中的数据发生更改时,bool 设置为 true,然后在更改员工时检查该标志
    • 实现IComparableIEquatable 接口
    • 覆盖Employee 和/或Memento 类的Equals 方法

    (如果您选择第二个选项,通常建议您完成第三个)

    示例

    这是您可以执行的操作的示例(我假设您有一个名为 listBox1ListBox,并且您已使用 listBox1_SelectedIndexChanged 函数附加到 SelectedIndexChanged 事件):

    private Employee lastSelectedEmployee;
    private Memento selectedMemento;
    
    void listBox1_SelectedIndexChanged(object sender, EventArgs e)
    {
        Employee selectedEmployee = (Employee)listBox1.SelectedItem;
    
        if(lastSelectedEmployee != null && lastSelectedEmployee != selectedEmployee)
        {
            if(/*changes exist*/)
            {
                if(/*cancel changes*/)
                {
                    listBox1.SelectedItem = lastSelectedEmployee;
    
                    return;
                }
            }
        }
    
        lastSelectedEmployee = selectedEmployee;
        selectedMemento = //create the memento based on selectedEmployee;
    }
    

    你必须为我离开 cmets 的区域提供你自己的逻辑,但这个想法应该很简单。

    【讨论】:

    • 亚当,你的回答真的很有帮助。 bt 我有一个疑问。在用户切换到另一位员工之前,我在哪里放置代码以进行比较。我是新手,请多多包涵。
    • @reggie:没有完全干净的方法可以做到这一点,因为ListBox 没有为您提供用于更改选择的可取消事件。您可能需要做的是将此代码放在SelectedItemChanged 事件中,然后如果用户选择取消,则将其设置回最后一个Employee(您必须缓存它)。
    • 哦...会尝试...谢谢亚当..请在一小时后为我的cmets查看问题...再次感谢..
    • 没有 selecteditemchanged 事件...但是 selectedvaluechanged...试过...不起作用
    • 我无法区分旧值和新值...当我在员工姓名框中输入消息时,它会给我所选员工的员工姓名。我现在的问题是弄清楚如何在更改列表中的员工之前将更改的值放入另一个对象中。然后比较旧对象和新对象。
    【解决方案2】:

    看看 IComparable 接口。它要求您实现不需要进行此类比较的方法。 KB article,希望它能为你转成英语,在我的电脑上它总是转成德语。

    -sa

    【讨论】:

    • MSDN:IComparable)>) 接口定义了 CompareTo 方法,该方法确定实现类型实例的排序顺序。 IEquatable)>) 接口定义了 Equals 方法,该方法确定实现类型实例的相等性。
    • CompareTo 如果比较对象相等,则返回值 0。因此,您可以使用 IComparable 来测试是否相等。一个副作用是排序比较。感谢您投票否决功能性答案。
    • 虽然我没有投反对票,但IComparable 接口设计用于排序和相对比较,而不是专门用于相等检查。在 2.0 之前,它是用于相等性检查的主要接口,但 2.0 引入了 IEquatable 接口(连同 IEqualityComparer 接口来补充 IComparer),它不需要实现能够确定哪个实例是“更大”,只是两个实例是否相等。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-19
    • 2019-08-02
    • 2014-01-26
    相关资源
    最近更新 更多