我正在实现一个名为Position
的结构,它代表一个包含属性double Latitude, Longitude, Elevation
的地理位置。
其中一个构造函数是
public Position(double lat, double lon, double elev)
我创建了另一个这样的:
public Position(IEnumerable<double> coords) : this(
coords.ElementAt(0),
coords.ElementAt(1),
coords.ElementAt(2)
) {}
这是有效的,但有点似乎“错误”我可以传递任何长度超过3的IEnumerable
,所以我的问题是:
coords
的长度,只接受coords.Count == 3
?IEnumerable<double>
以外的序列类型吗?答案 0 :(得分:2)
如果集合中的元素少于3个,则会中断,如果有更多元素,则会忽略第3个元素。你应该至少检查最小条件。但是,您将如何处理错误,抛出异常?这说明了为什么这可能不是一个好主意。
这是通用集合的正确参数。
是的,正如您所指出的,参数的数量对您的对象非常重要。允许集合删除该约束,并将错误放入运行时而不是编译时。我可以看到允许集合构造函数的任何优点。
答案 1 :(得分:2)
是的,如果错误,你应检查长度并抛出异常(可能ArgumentException
),因为这显然是一种例外情况。
没有任何类型的长度是类型签名的一部分。但是,您应该使用IList
以确保订单(与IEnumerable
不同),并且您可以通过索引访问。
您应该忘记以IEnumerable
传递,原因正如您所描述的那样。它只是一个不需要的潜在错误来源,而且它使您的签名不那么具有描述性,因此会降低您的代码的可读性。如果你可以在编译时防止错误,为什么要传递它?
但是,您可以考虑创建一个仅包含Coordinates
,Latitude
和Longitude
参数的Elevation
类。如果你需要做一些事情,比如转换到不同的坐标系,这也可以提供用。
答案 2 :(得分:2)
我实际上也不会通过IEnumerable
(同意其他人)。如果您可以使用序列来表示位置,那么为什么需要首先创建位置结构?您可以在代码中的所有位置使用IEnumerable
,不是吗? : - )
软件的一个重要原则是实现所需要的。你的代码中是否有IEnumerble
代表位置?如果没有,则跳过此构造函数,并仅在需要时添加它。但是,如果您有这样的需要,那么添加一个对参数计数不完全为3的检查以避免编码错误,如果坐标或高程的顺序与您预期的顺序不同,则可能仍然会出现编码错误。
在你的情况下,Position似乎是应该通过构造函数实例化的结构,例如
Position p = new Position(1, 2, 3);
或通过初始化属性,例如
Position p = new Position
{
Latitude = 1,
Longitude = 2,
Elevation = 3
};
答案 3 :(得分:1)
我同意这里的其他受访者 - 这个构造函数似乎可能导致问题,因为它没有清楚地记录所需的双值的数量。
但是,如果您需要来执行此操作,例如因为您有复杂的Linq查询返回您希望构建位置的地理位置信息,我注意到您的构造函数实际上遍历了Enumerable三每次调用ElementAt()一次。在使用复杂枚举器的情况下,这可能会导致性能问题。以下稍微不透明的代码可以避免该问题,并在给定的数据不足时抛出ArgumentException:
public class Position
{
public double lat, lon, elev;
public Position(IEnumerable<double> coords)
{
if (coords == null)
{
throw new ArgumentException();
}
using (var enumerator = coords.GetEnumerator())
{
if (enumerator != null && enumerator.MoveNext())
{
this.lat = enumerator.Current;
if (enumerator.MoveNext())
{
this.lon = enumerator.Current;
if (enumerator.MoveNext())
{
this.elev = enumerator.Current;
/*
if (enumerator.MoveNext())
{
// What to do here?? throw an exception?
throw new ArgumentException();
}*/
return;
}
}
}
}
throw new ArgumentException();
}
}
由您决定是否为太多数据抛出异常。
希望有所帮助。