代码之家  ›  专栏  ›  技术社区  ›  Oren Mazor

在C中动态装饰对象#

  •  10
  • Oren Mazor  · 技术社区  · 16 年前

    是否可以轻松地 动态地 装饰一个物体?

    例如,假设我有一个 List<PointF> . 这个列表实际上是正弦函数的一个图。我想通过这些点,在每个点F上添加一个标志,来判断它是否是一个峰值。

    但是我不想创建一个新的扩展的特殊点f或者其他什么,它有一个布尔属性。

    判断我你想做的一切,因为你懒惰,但懒惰是可怕的想法如何产生的(也是坏的想法)

    编辑:我会接受拳击解决方案以及你能想到的任何有趣的黑客。没有什么能真正阻止我去推导。我只想知道有没有更有趣的方法。

    4 回复  |  直到 16 年前
        1
  •  4
  •   Gabe Timothy Khouri    16 年前

    如果有一种方法可以计算每个点的值,则不需要向其添加标志,可以使用 extension 方法,而不必扩展它。

    类似于pointf.ispeak();

    它的工作原理如下:

    public static class Extensions
    {
        public static bool isPeak (this PointF p)
        {
            do crazy math...
    
            return result;
        }
    }
    

    瞧,你的计算在你的PointF类中。

    顺便说一下,公共静态类必须在最外面的范围内,不能嵌套。

        2
  •  5
  •   Adam Robinson    16 年前

    不,没有办法做你想要的事。

    假设您使用的是C 3.0+,那么您可以使用匿名类型来执行此操作,前提是您不希望在函数之外公开信息。

    var decoratedList = sourceList.Select(pt => new 
                        { 
                            IsPeak = GetIsPeak(pt), 
                            Point = pt 
                        }).ToList();
    

    这会给你一个新的 List<T> 对象。这很可能无法解决您的问题,因为您不能将此扩展到单个函数调用之外,并且您正在创建 新的 列出而不是修改现有的列表,但希望这有帮助。

        3
  •  3
  •   Ian Henry    16 年前

    可以 可以用新的 dynamic 关键字与 ExpandoObject 在C 4.0中构建,但我还没有第一手经验。据我所知,它是为了轻松解决这个确切的问题而创建的,所以你可以说

    dynamic something = new ExpandoObject();
    something.Anything = "whatever you want";
    

    相信 可以动态扩展现有类型,但可能需要创建一个新的子类,这将破坏练习的整个目的。

    可以使用扩展方法创建几乎相同的解决方案。这个 扩展对象 内部实现为 Dictionary 但它添加了经典的本机语法。

    class Program {
    
       static void Main(string[] args)
       {
          PointF p = new PointF(0, 0);
    
          p.SetFlag(true);
    
          if (p.GetFlag())
             Console.WriteLine("win");
       }
    
    }
    
    public static class Extensions
    {
       private static Dictionary<PointF, bool> flags = new Dictionary<PointF, bool>();
       public static bool GetFlag(this PointF key)
       {
          return flags[key];
          //OR return flags.ContainsKey(key) ? flags[key] : false;
       }
    
       public static void SetFlag(this PointF key, bool val)
       {
          flags[key] = val;
       }
    }
    
        4
  •  2
  •   Foxfire    16 年前

    不,不可能。

    最近的将只是创建一个

    var decorationData = new Dictionary <Object, bool>
    

    然后把你的价值保存在那里。不需要直接扩展类型。您甚至可以使用扩展方法来访问存储的数据,这看起来像是对象的直接属性。

    public static class PointFPeakExtensions
    { 
        private static var decorationData = new Dictionary <PointF, bool>
    
        public static bool IsPeak (this PointF point) 
        { 
            return decorationData[point];
        } 
        public static void SetPeak (this PointF point, bool isPeak) 
        { 
            decorationData[point] = isPeak;
        } 
    } 
    

    并添加到您的编辑:

    您还可以使用只包含修饰数据和引用类型的泛型类型来解决这个问题(与类库中实现可空类型的方法相同)。但是,这仍然意味着您必须在使用类型的地方更改签名(这可能不是您在查找装饰器时想要做的)。

    推荐文章