Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在c语言中动态装饰对象#_C#_Decorator - Fatal编程技术网

C# 在c语言中动态装饰对象#

C# 在c语言中动态装饰对象#,c#,decorator,C#,Decorator,是否可以轻松、动态地装饰对象 例如,假设我有一个列表。此列表实际上是正弦函数的绘图。我想遍历这些点,并在每个点F上添加一个标志,指示它是否为峰值 但我不想创建一个新的扩展SpecialPointF或其他任何具有布尔属性的东西 你想怎么评价我就怎么评价我吧,但是懒惰是产生好主意的原因(也是坏主意) 编辑:我会接受拳击解决方案以及你能想出的任何有趣的黑客。没有什么能真正阻止我推导。我只是想知道是否有更有趣的方式。不,没有办法(特别地)满足你的要求 假设您使用的是C#3.0+,您可以使用匿名类型来实现

是否可以轻松、动态地装饰对象

例如,假设我有一个
列表
。此列表实际上是正弦函数的绘图。我想遍历这些点,并在每个点F上添加一个标志,指示它是否为峰值

但我不想创建一个新的扩展SpecialPointF或其他任何具有布尔属性的东西

你想怎么评价我就怎么评价我吧,但是懒惰是产生好主意的原因(也是坏主意)

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

不,没有办法(特别地)满足你的要求

假设您使用的是C#3.0+,您可以使用匿名类型来实现这一点,前提是您不想在函数之外公开信息

var decoratedList = sourceList.Select(pt => new 
                    { 
                        IsPeak = GetIsPeak(pt), 
                        Point = pt 
                    }).ToList();
这将为您提供一个新的
列表
对象。这很可能无法解决您的问题,因为您无法在单个函数调用之外扩展它,并且您正在创建一个新列表,而不是修改现有列表,但希望这能有所帮助。

不,这是不可能的

最近的将只是创建一个

var decorationData = new Dictionary <Object, bool>
var decorationData=新字典
然后将您的值保存在其中。不需要直接扩展类型。您甚至可以使用扩展方法访问存储的数据,这些数据看起来像是对象的直接属性

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;
    } 
} 
公共静态类PointFPeakExtensions
{ 
私有静态var decorationData=新字典
公共静态布尔IsPeak(此点F点)
{ 
返回装饰数据[点];
} 
公共静态无效设置峰值(此点F点,布尔值为峰值)
{ 
装饰数据[点]=isPeak;
} 
} 
并添加到您的编辑:


您还可以使用仅包含装饰数据和引用类型的泛型类型来解决此问题(与类库中实现可空类型的方式相同)。然而,这仍然意味着您必须在使用该类型的位置更改签名(这可能不是您在寻找decorator时想要做的)。

如果有一种方法可以计算每个点的签名,您不需要向其添加标志,您可以使用一种方法,而无需扩展它

类似于PointF.isPeak()的内容

它的工作原理如下:

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

        return result;
    }
}
瞧,你的计算在你的PointF类中

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

使用C#4.0中的new关键字和
ExpandoObject
construct可以做到这一点,但我还没有第一手的经验。据我所知,创建它是为了轻松解决这个确切的问题,所以你可以这么说

dynamic something = new ExpandoObject();
something.Anything = "whatever you want";
我相信动态扩展现有类型是可能的,但它可能需要创建一个新的子类,这将破坏整个练习的目的

可以使用扩展方法创建几乎相同的解决方案。
ExpandoObject
在内部实现为一个
字典
,但它添加了一流的本地语法

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;
   }
}
类程序{
静态void Main(字符串[]参数)
{
点F p=新点F(0,0);
p、 SetFlag(真);
if(p.GetFlag())
Console.WriteLine(“win”);
}
}
公共静态类扩展
{
私有静态字典标志=新字典();
公共静态bool GetFlag(此PointF键)
{
返回标志[键];
//或返回标志。ContainsKey?标志[key]:false;
}
公共静态无效设置标志(此PointF键,布尔值)
{
标志[key]=val;
}
}

我刚刚给了你+1作为结束语。不过,我不太确定你的问题的答案。这是个很酷的主意。我还没有使用匿名类型,所以我甚至没有考虑过它。我们使用最新的c#很酷,所以这不是问题。@Oren:它们很好,但最大的警告是不能将它们暴露在您的函数之外。如果您需要这样做,您必须创建自己的具有类似签名的简单包装类,然后只需说
newwrappersclass{…
,而不仅仅是
new{…
+1。这是一个很好的建议,尽管
isPeak
的命名与.NET命名约定不一致(第一个字符应该大写)这是个很棒的主意。我喜欢它。@Francisco:扩展方法是个好主意,但在这种情况下,一个点如何知道它是否是它不包含的序列中的峰值?除非该点包含指向它所属序列的指针…@Partha我想我将把上一个和下一个点传递给IsPeak。我相信我可以做更多的数学杂耍用微积分找到峰值,但这有点像“我知道!我会用正则表达式来解决这个问题!”的情况:)@Partha:不行(“做疯狂的数学”是不可能的,不知道级数)。但是你可以用类似的方法。看我对这个问题的回答。你是不是想调用Extensions.SetFlag(p,true)而不是p.SetFlag不,扩展方法允许您进行类似“本机”的调用。它会自动为您调用
Extensions.SetFlag(p,true)