是否可以轻松地动态装饰对象?
例如,假设我有List<PointF>
。这个列表实际上是正弦函数的图。我想通过这些观点为每个PointF添加一个标志,告知它是否是一个高峰。
但是我不想创建一个新的扩展SpecialPointF或者其他什么,它有一个布尔属性。
判断我想要懒惰的一切,但懒惰是多么出色的想法诞生(也是糟糕的想法)
编辑:我会接受拳击解决方案以及你能想到的任何有趣的黑客攻击。没有什么可以阻止我的衍生。我只是想知道是否有更有趣的方式。
答案 0 :(得分:5)
不,没有办法(具体地)你要求的东西。
假设您使用的是C#3.0+,您可以使用匿名类型来执行此操作,假设您不希望在函数之外公开信息。
var decoratedList = sourceList.Select(pt => new
{
IsPeak = GetIsPeak(pt),
Point = pt
}).ToList();
这将为您提供一个新的List<T>
对象。这可能无法解决您的问题,因为您无法在单个函数调用之外扩展它,并且您正在创建 new 列表而不是修改现有的列表,但希望这会有所帮助。
答案 1 :(得分:4)
如果有一种方法可以计算每个点,你不需要为它添加一个标记,你可以使用extension方法而不必扩展它。
像PointF.isPeak();
它的作用类似于:
public static class Extensions
{
public static bool isPeak (this PointF p)
{
do crazy math...
return result;
}
}
瞧,你在PointF课上有计算。
顺便说一句,公共静态类必须在最外层,不能嵌套。
答案 2 :(得分:3)
可能可以使用C#4.0中的新dynamic关键字和ExpandoObject
构造来实现此目的,但我还没有第一手经验。据我所知,它是为了轻松解决这个问题而创建的,所以你可以说
dynamic something = new ExpandoObject();
something.Anything = "whatever you want";
我相信可以动态扩展现有类型,但可能需要创建一个新的子类,这会破坏练习的整个目的。
可以使用扩展方法创建几乎相同的解决方案。 ExpandoObject
在内部实现为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;
}
}
答案 3 :(得分:2)
不,这是不可能的。
最近的只是创建一个
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;
}
}
并添加到您的编辑中:
您也可以使用仅包含装饰数据和引用类型的泛型类型来解决此问题(与类库中实现Nullable类型的方式相同)。但是,这仍然意味着您必须在使用该类型的位置更改签名(这可能不是您在查找装饰器时要执行的操作)。