【问题标题】:How to use List<T>() to hide private fields?如何使用 List<T>() 隐藏私有字段?
【发布时间】:2019-01-23 13:43:15
【问题描述】:

我创建了一个 DatesClass,从中获取 Date 数据,这些数据存储在字符串中(出于某种原因——我知道我可以使用 DateTime——)在 Microsoft SQL Server localdb 数据库中使用System.Data.Linq.Mapping 就像这个:

[Column(CanBeNull = false)]
private string FirstDate { get; set; } = string.Empty;

[Column(CanBeNull = false)]
private string SecondDate { get; set; } = string.Empty;

[Column(CanBeNull = false)]
private string ThirdDate { get; set; } = string.Empty;

(我将它们全部设为私有,因为我不希望任何人在课堂外直接访问它们,包括我)

但是,我制作了一个包含所有内容的列表。像这样:

private List<DateTime> _dates;

public List<DateTime> Dates {
    get {
        var f    = DateTime.TryParse(FirstDate,  out var first);
        var s    = DateTime.TryParse(SecondDate, out var second);
        var t    = DateTime.TryParse(ThirdDate,  out var third);
        var list = new List<DateTime>();
        if (f) list.Add(first);
        if (s) list.Add(second);
        if (t) list.Add(third);
        if (_dates != null) return list;
        _dates = list;
        return list;
    }
    private set {
        FirstDate  = value[0].ToShortDateString();
        SecondDate = value[1].ToShortDateString();
        ThirdDate  = value[2].ToShortDateString();
    }
}

然后做了一个方法来添加日期到列表中:

public void AddDate(DateTime date) {
    if (_dates == null) // this was added because some parts of `Dates` getter didn't work for some reason
        _dates = Dates;

    if (_dates.Count == 3)
        throw new ManyDatesException(); // custom exception

    if (_dates.Contains(date))
        return;

    _dates.Add(date);
}

然后全部保存:

public void SaveDates() {
    // this saves data of `_dates` to the private fields using the setter of `Dates`
    Dates = _dates;
}

然后我会通过 WPF 中的各种事件和按钮来做逻辑:

private void AddDates_Click(object sender, RoutedEventArgs e) {
    var date = IDatePicker.SelectedDate ?? IDatePicker.DisplayDate;
    var datesClass = DatesProvider.GetDatesClass(1);
    var anotherDatesClass = DatesProvider.GetDatesClass(2);
    if (datesClass.Dates.Contains(date)) {
        Debug.Show(new DateAlreadyExistException()); // custom function for showing exception messages
        return;
    }

    try {
        datesClass.AddMonth(date);
    } catch (ManyDatesException ex) {
        Debug.Show(ex);
        return;
    }

    // save everything to the actual database
}

但我遇到了一系列严重的问题,其中一些是:

  • 点击事件多次触发(已退订并订阅点击事件)
  • 即使在获得公共Date 列表并假定在那里设置私有_dates 之后,_dates 仍然为空且未分配。
  • 不知何故,当第一次触发点击事件并在AddDate(DateTime date) 中分配_dates 时,它不会继续执行AddDate() 方法的其余部分,而是在已经分配_dates 时继续。

这太令人沮丧了,我将不胜感激。

【问题讨论】:

  • 这可能令人沮丧,因为私有属性是一个奇怪的概念。您也许可以将它们设为只读,即使用私人设置器。
  • 该代码非常复杂。上课的目的到底是什么?
  • @Clemens 我想以列表的形式访问私有属性并将它们保存为属性,以便它们实际上可以保存到数据库中,因为 sql 不支持数组和此类对象。
  • @RufusL 使用 linq to sql 检索并保存大量日期到 sql 数据库中。
  • 但是那里有太多令人困惑的逻辑,很难说出要求是什么或为什么要这样做。

标签: c# wpf linq oop properties


【解决方案1】:

我认为问题的一部分在于您正在尝试协调 3 个私有字段和一个私有列表,并且有时列表或字段会更新,而另一个不会更新。

根据您的 cmets 和您共享的代码,似乎确实不需要私有 List&lt;DateTime&gt; _dates。听起来您只需要 3 个私有属性(我猜是为了数据绑定?),您想将它们公开为列表,并且您想提供一种添加日期的方法。

如果这一切都是真的,那么您应该能够在没有实际私有列表的情况下封装您的字段:

public class DatesClass
{
    [Column(CanBeNull = false)]
    private string FirstDate { get; set; } = string.Empty;

    [Column(CanBeNull = false)]
    private string SecondDate { get; set; } = string.Empty;

    [Column(CanBeNull = false)]
    private string ThirdDate { get; set; } = string.Empty;

    public List<DateTime> Dates
    {
        get
        {
            var dates = new List<DateTime>();
            DateTime temp;
            if (DateTime.TryParse(FirstDate, out temp)) dates.Add(temp);
            if (DateTime.TryParse(SecondDate, out temp)) dates.Add(temp);
            if (DateTime.TryParse(ThirdDate, out temp)) dates.Add(temp);
            return dates;
        }
    }

    public void AddDate(DateTime date)
    {
        if (Dates.Contains(date)) return;

        if (string.IsNullOrEmpty(FirstDate)) FirstDate = date.ToShortDateString();
        else if(string.IsNullOrEmpty(SecondDate)) SecondDate = date.ToShortDateString();
        else if(string.IsNullOrEmpty(ThirdDate)) ThirdDate = date.ToShortDateString();
        else throw new ManyDatesException();
    }
}

【讨论】:

  • 没想到这么简单。
猜你喜欢
  • 2011-03-15
  • 1970-01-01
  • 1970-01-01
  • 2021-06-14
  • 2019-04-03
  • 2011-11-23
  • 1970-01-01
  • 2013-04-06
  • 2011-07-25
相关资源
最近更新 更多