c# - .NET 中是否有任何类型指示内部对象是否已初始化?

标签 c# .net

我知道标题很困惑。以下是我的场景

我的服务有一个契约(Contract)对象,如下所示。

class UpdateRequest
{
   public int EmployeeId { get; set; }
   public string EmployeeName { get; set; }
   public decimal Salary { get; set; }
}

现在,上述类的合约对象被传递给更新数据库中记录的方法。假设我想更新一个 ID 为 33 的员工,但我只想更改其名称,而我想单独保留薪水。

一种方法是不用担心这些细节并更新所有内容,但这需要我的服务的客户也将薪水值传递给我,这样它就不会被覆盖为默认(十进制)值。

我能想到的另一种方法是创建以下类型

public class TrackedValue<TInternal> : where TInternal:new
{
  private TInternal value = default(TInternal);
  public TInternal Value { get; }
  private bool initialized;

  public static implicit operator TrackedValue<TInternal>(TInternal v)
  {
     return new TrackedValue<TInternal> { value = v, initialized = true };
  }
}

还有别的办法吗? .NET 没有像上面那样的东西吗?我假设如果他们有像 Nullable 这样的东西,他们也必须有解决这个问题的东西。

可空类型对我没有帮助。在某些用例中,我必须将某些表列的现有值更改为 null。那会把它扔掉。

更新:有些人可能会说,我的服务应该根据该类型的默认值检查属性值。 “bool”的默认值为 false,如果调用我的方法时 bool 属性值为 false,这将破坏我的逻辑。

最佳答案

你的 TrackedValue类(class)非常准确。但是,您有点重新发明了轮子。这已经被称为 Maybe<T>单子(monad)。

查看“可能”monad,您会得到很多细节,但这里是:

public class Maybe<T>
{
   public readonly static Maybe<T> Nothing = new Maybe<T>();

   public T Value { get; private set; }
   public bool HasValue { get; private set; }

   public Maybe()
   {
       HasValue = false;
   }

   public Maybe(T value)
   {
       Value = value;
       HasValue = true;
   }
}

它非常像可空类型,但不限于值类型。

所以你可以这样:

class UpdateRequest
{
   public int EmployeeId { get; set; }
   public Maybe<string> EmployeeName { get; set; }
   public Maybe<decimal> Salary { get; set; }
}

例如,如果您只想更新薪水,那么您可以像这样初始化类:

var request = new UpdateRequest()
{
    EmployeeId = 1234,
    EmployeeName = Maybe<string>.Nothing,
    Salary = new Maybe<decimal>(50000m),
};

或者你可以定义一个 .ToMaybe()像这样的扩展方法:

   public static Maybe<T> ToMaybe<T>(this T value)
   {
       return new Maybe<T>(value);
   }

然后初始化看起来像这样:

var request = new UpdateRequest()
{
    EmployeeId = 1234,
    EmployeeName = Maybe<string>.Nothing,
    Salary = 50000m.ToMaybe(),
};

或者你可以像这样添加一个隐式运算符:

   public static implicit operator Maybe<T>(T v)
   {
       return v.ToMaybe();
   }

现在初始化更简单了:

var request = new UpdateRequest()
{
    EmployeeId = 1234,
    EmployeeName = Maybe<string>.Nothing,
    Salary = 50000m,
};

然后您应该为类型定义两个“绑定(bind)”运算符 - 即 SelectMany在 linq 中——像这样:

  public static Maybe<U> Select<T, U>(this Maybe<T> m, Func<T, U> k)
   {
        return m.SelectMany(t => k(t).ToMaybe());
   }

    public static Maybe<U> SelectMany<T, U>(this Maybe<T> m, Func<T, Maybe<U>> k)
   {
       if (!m.HasValue)
       {
           return Maybe<U>.Nothing;
       }
       return k(m.Value);
   }

   public static Maybe<V> SelectMany<T, U, V>(this Maybe<T> m, Func<T, Maybe<U>> k, Func<T, U, V> s)
   {
       return m.SelectMany(x => k(x).SelectMany(y => s(x, y).ToMaybe()));
   }

现在您可以针对可能值执行 LINQ 查询。

Maybe<decimal> tax =
    from salary in request.Salary
    select salary * 0.1m;

然后,如果request.SalaryNothing然后 tax将是 Nothing .否则将执行计算。

希望对您有所帮助。

关于c# - .NET 中是否有任何类型指示内部对象是否已初始化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26985177/

相关文章:

c# - 在 Parallel.For 中发送多个 WebRequest

c# - 如何获得方法参数的名称?

C# 泛型和推断类型

c# - 使用 C# 添加机会记录

c# - WinRT 中的 DataContractSerializer

c# - 让事件符合 Net 指南有什么好处?

.net - 我对 dumpheap 和 gcroot 的理解不正确吗

.net - Asp.Net Core RC2 与 Microsoft.Owin

C#/.NET : Can I get a string of valid HTML from a Stream?

c# - 从 Visual Studio 2012 插件创建连接的查询窗口