代码之家  ›  专栏  ›  技术社区  ›  Joel Barsotti

属性作为参数?C.*

  •  0
  • Joel Barsotti  · 技术社区  · 16 年前

    所以我有很多选项,每个不同的页面/标签都有自己的本地选项。我们将有10-15页的标签打开顶部。我需要实现一种显示全局默认值的方法,看看所有选项卡的值是否一致。我正在研究WPF应用程序的模型/视图模型部分。

    我很想找到一种更优雅的方法,因为我必须剪切和跳过大致相同的代码20多次,然后只需更改属性名。也许这是动力学解决的问题,但现在这感觉既错误又痛苦。

    下面是我当前解决方案的一个示例:

    public class Foo
    {
        private bool fooVar1;
        private bool fooVar2;
        //lots of these
        private decimal fooVar23;
    
        public Foo()
        {
        }
    
        public bool FooVar1
        {
            get;
            set;
        }
    
        //you get the picture...
    }
    
    public class FooMonitor
    {
        private Foo defaultFoo;
        private List<Foo> allFoos;
    
        public FooMonitor(Foo DefaultFoo)
        {
            defaultFoo = DefaultFoo;
        }
    
        public void AddFoo(Foo newFoo)
        {
            allFoos.Add(newFoo);
        }
    
        public void AddFoo(Foo oldFoo)
        {
            allFoos.Remove(oldFoo);
        }
    
        public bool IsFooVar1Consistent
        {
            get
            {
                Foo[] tempFoos = allFoos.ToArray();
                foreach (Foo tempFoo in tempFoos)
                {
                    if (tempFoo.FooVar1 != defaultFoo.FooVar1) return false;
                }
                return true;
            }
        }
    }
    

    或者我是完全错误地处理这个问题。 在我写这个问题的时候(大约2000行代码之后),我在想我是如何理解WPF本身实现字典查找的,这些字典查找向上爬到父级以查看属性是否存在以及值应该是什么。

    3 回复  |  直到 16 年前
        1
  •  2
  •   Juliet    16 年前

    我很想找到一种方法 优雅,因为我必须切割 经过大致相同的代码20多次 只需更改属性名。

    代码生成器的存在正是为了这个目的。但如果您不想走这条路,可以将代码缩短为:

    return allFoos.All(foo => foo.FooVar1 == defaultFoo.FooVar1);
    
        2
  •  3
  •   David M    16 年前

    首先,您定义了两个永远不会使用的支持字段和自动属性。这就足够了 bool 财产:

    public bool FooVar1 { get; set; }
    

    不需要私人领域。这大大减少了示例中的行数。

        3
  •  2
  •   itowlson    16 年前

    我不太确定问题是什么,但是如果您正在寻找某种方法来统一isfoorvarxconsistent代码,您可以使用反射或通过传递表达式来实现:

    public bool IsConsistent(Func<Foo, bool> property)
    {
      foreach (Foo tempFoo in allFoos)
      {
        if (property(tempFoo) != property(defaultFoo))
          return false;
      }
      return true;
    }
    

    这样称呼:

    bool is1Consistent = IsConsistent(f => f.FooVar1);
    

    如图所示,这仅适用于布尔属性。要将其扩展到其他类型,可以在属性类型中使其成为泛型。但是,在这种情况下,我们不能使用!=测试不等式,因为不是所有类型都定义了a!=算符。相反,我们可以使用.equals方法和!操作员:

    public bool IsConsistent<T>(Func<Foo, T> property)
      where T : struct
    {
      foreach (Foo tempFoo in allFoos)
      {
        if (!property(tempFoo).Equals(property(defaultFoo)))
          return false;
      }
      return true;
    }
    

    这个 where T : struct 子句将此限制为int、bool和decimal等值类型。尤其是它在字符串上不起作用。去掉 where 约束允许它处理字符串和其他引用类型,但创建了 property(tempFoo) 为空,这将在调用它的.equals时导致NullReferenceException。因此,如果删除值类型约束,则需要为此方案添加错误处理。