在访问器 C# 中调用方法

Calling a method inside an accessor C#

所以我已经为此苦苦挣扎了一段时间。
我正在尝试学习 OOP,但这太大了,至少我很难理解它。
假设我在 class 中有一个方法可以从数据库中获取一些东西。
此数据将设置为变量。
我现在要做的是有一个 public 方法,调用它,然后用值调用访问器。例如:

        private string _name;

        public string Name { get { return _name; } }

        public void MyMethod()
        {
            using (SqlConnection connect = new SqlConnection(connectionString))
            {
                using (SqlCommand command = new SqlCommand("SELECT Name FROM Table WHERE ID = 1", connect))
                {
                    connect.Open();
                    using (SqlDataReader reader = command.ExecuteReader())
                    {
                        if (reader.Read())
                        {
                            _name = Convert.ToString(reader["Name"]);
                        }
                    }
                }
            }
        }

我会这样称呼它:

MyClass myclass = new MyClass();
myclass.MyMethod();
string myname = myclass.Name;

现在这对我来说真的很奇怪。
所以我想,也许在访问器内部调用方法是值得的。
喜欢:

public string Name { get { MyMethod(); return _name; } }

这样称呼它:

MyClass myclass = new MyClass();
string myname = myclass.Name;

这会减少代码,我可以将我的方法设为私有。
然而,当方法有参数时,我会遇到麻烦。
那么我该怎么做呢?这是不好的做法吗?如果这不是我应该做的,那我该怎么做呢?

我真的很想听听你们的意见!请随时提问或修改我的问题。
另外,如果已经有人问过这个问题,我深表歉意。
任何很棒的教程也非常受欢迎!

需要注意的重要一点是,这两件事(保存数据的对象和获取数据的方法)是两个截然不同的问题。好的做法是您的 classes 有一个 separation of concerns.

在您的情况下,您应该有一个知道如何从数据库获取数据的 "repository" class 和一个具有属性的 DTO(或简单地说,对象)。您的存储库可能会加载所有需要的数据和 return 一个包含所有数据的对象。

  • 你可以考虑运行 ctor 中的方法一次。

  • 你可以有一个 public RefreshData 方法,它将从数据库更新你需要的所有内容。

  • 您可以让 属性 检查 _name 是否为空,并且仅当它为空时 - 它会从数据库更新它然后 return 它- 否则它只是 return 的现有值。您可以将它与 Invalidate 方法结合使用,该方法会将 _name 和任何其他相关成员设置为 null 或其他一些指示,以使它们的属性在下次调用时确实重新调用更新函数.

在现实生活中,您通常会知道什么是更好的方法 - 但它们都是 OOP。

但是您建议的解决方案有点违反 OOP 原则,因为 MyMethod 可能不应该公开,而您的 class 可能是负责其数据的人。


此外,正如 Jamiec 的回答所建议的那样,您应该在其他地方实现与数据库相关的逻辑,在存储库 class 甚至整个层(有时是单独的项目)中(寻找 DAL)。这是因为即使您的 class 可能对其自己的数据负责 - 它不应该 "know" 任何关于数据库或查询语言的事情。至多 - 它知道如何向独立于它的东西请求一些数据。

您正在实施的是 Lazy Evaluation 的一种形式 有时称为 cached 属性

一般的设计模式是:

private SomeType _value;
public SomeType CachedProperty {
     get {
          if(_value == null) {
              _value = GetValue(); // slow
          }
          return _value;
     }
}

有几个原因阻碍了这种 属性 的想法:

  • GetValue() 通常很慢。这就是为什么我们首先兑现它的价值。所以访问 属性 只是在第一次调用时很慢。 但是我们希望属性总是快。

  • 当我们再次需要它时,兑现价值可能已经过时了。这可以通过像 UpdateValue 这样的 public 方法来缓解。 但是 我们希望 属性 始终 是最新的。

  • 如果省略 _value == null 检查,则 属性 将成为 方法 的包装器。为什么我们要使用 属性 呢?

因此,从本质上讲,这种设计模式 隐藏了 基础价值本质上是易变的并且可能需要一些时间才能恢复的事实。

你是否真的想这样做,取决于你周围代码的需求。

但总的来说,我会采用典型的异步模式:

public SomeType GetValue() { ... }
public Task<SomeType> GetValueAsync() { ... }

如果您确实需要在不同范围内使用缓存值,请添加:

public SomeType CachedValue { get; }

这表明您获得的 "fast way" 值可能已过时。