我在C#(2.0)中编写一个必须返回简单对象集合的方法.通常我会做这样的事情:
class MyWidget
{
struct LittleThing
{
int foo;
DateTime bar;
}
public IList<LittleThing> LookupThings()
{
// etc.
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我必须在接口中声明此方法.调用者无法看到MyWidget,只有一个IWidget界面.上述设置在这种情况下不起作用,因为C#不允许在接口内定义类型.做这种声明的正确或最佳方式是什么?
我想到的直接的事情是简单地LittleThing在界面之外声明.出于几个原因,这看起来并不好.一:它只用于那个单一类中的那个单一方法,所以它似乎不LittleThing应该是一个独立的类型,只是自己浮动.二:如果为其他类编写类似的方法,它们将返回不同类型的数据(出于良好的设计原因),并且我不希望使用大量相似命名的结构来混淆名称空间彼此.
如果我们可以升级我们的.Net版本,我只会返回一个Tuple<>,但这还不是一段时间的选择.
[编辑添加:小对象确实需要包含两个以上的字段,因此KeyValuePair<K,V>不会完全删除它.]
[编辑进一步补充:IWidget仅由一个类实现,Widget.我认为只有一个类的接口很奇怪,但这样做是为了满足旧的编码策略,该策略要求契约始终与实现分开.所述政策现已消失,但我们没有资源重构整个应用程序并删除所有不必要的接口.]
什么是最佳做法?
如果"LittleThing"只有两个值,则可以返回a KeyValuePair<TKey,TValue>.
如果有两个以上,你可以随时创建自己的Tuple类,并在最终转移到.NET 4时将其替换为.NET 4.
否则,我只想用接口定义结构,并将其作为API的一部分包含在内.命名空间负责命名问题......
如果我们可以升级 .Net 版本,我只会返回一个 Tuple<>,但在一段时间内这还不会成为一个选项。
为什么要等?元组并不是一件复杂的事情。这是三元组的代码。
public struct Tuple<TItem1, TItem2, TItem3>
{
public Tuple(TItem1 item1, TItem2 item2, TItem3 item3)
{
this = new Tuple<TItem1, TItem2, TItem3>();
Item1 = item1;
Item2 = item2;
Item3 = item3;
}
public static bool operator !=(Tuple<TItem1, TItem2, TItem3> left, Tuple<TItem1, TItem2, TItem3> right)
{ return left.Equals(right); }
public static bool operator ==(Tuple<TItem1, TItem2, TItem3> left, Tuple<TItem1, TItem2, 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, TItem2, TItem3>)
{
var other = (Tuple<TItem1, TItem2, 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);
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,这没什么大不了的。我在当前项目中所做的是实现 2、3 和 4 元组,以及一个Tuple带有方法的静态类Create,它完全反映了 .NET 4 元组类型。如果您真的很偏执,您可以使用 Reflector 查看 .NET 4 元组的反汇编源代码,然后逐字复制它
当我们最终升级到 .NET 4 时,我们将删除这些类,或者将#ifdef它们删除