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)
。