我在C#(2.0)中编写一个必须返回简单对象集合的方法.通常我会做这样的事情:
class MyWidget { struct LittleThing { int foo; DateTime bar; } public IList<LittleThing> LookupThings() { // etc. } }
但是,我必须在接口中声明此方法.调用者无法看到MyWidget,只能看到IWidget接口.上述设置在这种情况下不起作用,因为C#不允许在接口内定义类型.做这种声明的正确或最佳方式是什么?
我想到的直接的事情是简单地在界面之外声明LittleThing.出于几个原因,这看起来并不好.一:它只用于那个单一类中的单一方法,所以LittleThing似乎不应该只是一个独立的类型.二:如果为其他类编写类似的方法,它们将返回不同类型的数据(出于良好的设计原因),并且我不希望使用大量相似命名的结构来混淆名称空间彼此.
如果我们可以升级我们的.Net版本,我只会返回一个Tuple<>,但这还不是一段时间的选择.
[编辑添加:小对象确实需要包含两个以上的字段,因此KeyValuePair< K,V>不会削减它.]
[编辑进一步补充:IWidget只由一个类Widget实现.我认为只有一个类的接口很奇怪,但这样做是为了满足旧的编码策略,该策略要求契约始终与实现分开.所述政策现已消失,但我们没有资源重构整个应用程序并删除所有不必要的接口.]
什么是最佳做法?
解决方法
If we could upgrade our version of .Net,I would just return a Tuple<>,but that’s not going to be an option for some time yet.
干嘛要等?它不像元组是一件复杂的事情.这是3元组的代码.
public struct Tuple<TItem1,TItem2,TItem3> { public Tuple(TItem1 item1,TItem2 item2,TItem3 item3) { this = new Tuple<TItem1,TItem3>(); Item1 = item1; Item2 = item2; Item3 = item3; } public static bool operator !=(Tuple<TItem1,TItem3> left,Tuple<TItem1,TItem3> right) { return left.Equals(right); } public static bool operator ==(Tuple<TItem1,TItem3> right) { return !left.Equals(right); } public TItem1 Item1 { get; private set; } public TItem2 Item2 { get; private set; } public TItem3 Item3 { get; private set; } public override bool Equals(object obj) { if (obj is Tuple<TItem1,TItem3>) { var other = (Tuple<TItem1,TItem3>)obj; return Object.Equals(Item1,other.Item1) && Object.Equals(Item2,other.Item2) && Object.Equals(Item3,other.Item3); } return false; } public override int GetHashCode() { return ((this.Item1 != null) ? this.Item1.GetHashCode() : 0) ^ ((this.Item2 != null) ? this.Item2.GetHashCode() : 0) ^ ((this.Item3 != null) ? this.Item3.GetHashCode() : 0); } }
如你所见,这没什么大不了的.我在当前项目中所做的是实现2,3和4元组,以及带有Create方法的静态Tuple类,它完全反映了.NET 4元组类型.如果你真的是偏执狂,你可以使用反射器来查看.NET 4元组的反汇编源代码,并逐字复制