问题描述
我有一个专门的列表保存类型为 IThing
的项目:
I have a specialized list that holds items of type IThing
:
public class ThingList : IList<IThing>
{...}
public interface IThing
{
Decimal Weight { get; set; }
Decimal Velocity { get; set; }
Decimal Distance { get; set; }
Decimal Age { get; set; }
Decimal AnotherValue { get; set; }
[...even more properties and methods...]
}
有时候,我需要知道所有的事情列表中的某个属性的最大值或最小值。由于告诉不问我们让列表图吧:
Sometimes I need to know the maximum or minimum of a certain property of all the things in the list. Because of "Tell don't ask" we let the List figure it out:
public class ThingList : IList<IThing>
{
public Decimal GetMaximumWeight()
{
Decimal result = 0;
foreach (IThing thing in this) {
result = Math.Max(result, thing.Weight);
}
return result;
}
}
那是非常好的。但有时我需要的最小重量,有时最大速度等。我不希望有一个 GetMaximum *()/ GetMinimum *()
对每一个单独的属性。
Thats very nice. But sometimes I need the minimum weight, sometimes the maximum velocity and so on. I don't want a GetMaximum*()/GetMinimum*()
pair for every single property.
一个解决办法是反思。喜欢的东西(捏住鼻子,强code味道!)
One solution would be reflection. Something like (hold your nose, strong code smell!):
Decimal GetMaximum(String propertyName);
Decimal GetMinimum(String propertyName);
有没有更好的,更小臭的方式来做到这一点?
Are there any better, less smelly ways to accomplish this?
谢谢,埃里克
编辑:@ 马特:NET 2.0
@Matt: .Net 2.0
结论:对于.NET 2.0没有更好的办法(与Visual Studio 2005)。也许我们应该移动到.NET 3.5和Visual Studio 2008年的某个时候推出。谢谢你,伙计们。击>
结论:有diffent方式远比反映好。根据运行时和C#版本。看一看的差异乔恩长柄水杓答案。所有的答案都非常有帮助的。
Conclusion: There are diffent ways that are far better than reflection. Depending on runtime and C# version. Have a look at Jon Skeets answer for the differences. All answers are are very helpful.
我会去Sklivvz建议(匿名方法)。还有其他几个人的code段(康拉德·鲁道夫,马特·汉密尔顿和Coincoin)的实施Sklivvz想法。我只能接受一个答案,很遗憾。
I will go for Sklivvz suggestion (anonymous methods). There are several code snippets from other people (Konrad Rudolph, Matt Hamilton and Coincoin) which implement Sklivvz idea. I can only "accept" one answer, unfortunately.
非常感谢你。你可以都觉得接受,altough只Sklivvz得到信贷; - )
Thank you very much. You can all feel "accepted", altough only Sklivvz gets the credits ;-)
推荐答案
是的,你应该使用一个代理和匿名方法。
Yes, you should use a delegate and anonymous methods.
有关的例子请参见这里。
基本上你需要实现类似于查找方法的东西的名单的。
Basically you need to implement something similar to the Find method of Lists.
下面是一个简单的执行
public class Thing
{
public int theInt;
public char theChar;
public DateTime theDateTime;
public Thing(int theInt, char theChar, DateTime theDateTime)
{
this.theInt = theInt;
this.theChar = theChar;
this.theDateTime = theDateTime;
}
public string Dump()
{
return string.Format("I: {0}, S: {1}, D: {2}",
theInt, theChar, theDateTime);
}
}
public class ThingCollection: List<Thing>
{
public delegate Thing AggregateFunction(Thing Best,
Thing Candidate);
public Thing Aggregate(Thing Seed, AggregateFunction Func)
{
Thing res = Seed;
foreach (Thing t in this)
{
res = Func(res, t);
}
return res;
}
}
class MainClass
{
public static void Main(string[] args)
{
Thing a = new Thing(1,'z',DateTime.Now);
Thing b = new Thing(2,'y',DateTime.Now.AddDays(1));
Thing c = new Thing(3,'x',DateTime.Now.AddDays(-1));
Thing d = new Thing(4,'w',DateTime.Now.AddDays(2));
Thing e = new Thing(5,'v',DateTime.Now.AddDays(-2));
ThingCollection tc = new ThingCollection();
tc.AddRange(new Thing[]{a,b,c,d,e});
Thing result;
//Max by date
result = tc.Aggregate(tc[0],
delegate (Thing Best, Thing Candidate)
{
return (Candidate.theDateTime.CompareTo(
Best.theDateTime) > 0) ?
Candidate :
Best;
}
);
Console.WriteLine("Max by date: {0}", result.Dump());
//Min by char
result = tc.Aggregate(tc[0],
delegate (Thing Best, Thing Candidate)
{
return (Candidate.theChar < Best.theChar) ?
Candidate :
Best;
}
);
Console.WriteLine("Min by char: {0}", result.Dump());
}
}
结果:
最大按日期:I:4,S:W,D:2008年10月3号上午12点44分零七秒
闵成炭:我:5,S:V,D:2008年9月29日上午12点44分○七秒
这篇关于C#中:获取列表中的所有项目的任意属性的最大值和最小值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!