我想创建一个接受Position对象的函数,并将此Position的纬度和经度作为格式化字符串返回。
但问题是我有2个Position对象:一个来自Xamarin Forms,另一个来自地理定位金块。
Xamarin表格中的位置:
public Position(double latitude, double longitude);
public double Latitude { get; }
public double Longitude { get; }
...
来自地理定位金块的位置:
public Position();
public Position(Position position);
public double Latitude { get; set; }
public double Longitude { get; set; }
...
为了使这两种类型合为一体,我创建了一个界面:
interface IPosition
{
double Latitude
{
get;
set;
}
double Longitude
{
get;
set;
}
}
所以我的函数应该接受参数中的这两个对象,如下所示:
public static string PositionToCoordonates<T>(T p)
{
return ((IPosition)p).Latitude.ToString().Replace(",", ".") + " ," + ((IPosition)p).Longitude.ToString().Replace(",", ".");
}
不幸的是,它在运行时抛出错误“ System.InvalidCastException:指定的强制转换无效。”。
我做错了什么?我想我需要某种动态演员,但我不确定。
答案 0 :(得分:3)
PositionToCoordonates
不应该是通用的。使其通用是一种说法,参数可以是任何类型的 。您的参数可以是任何类型,它必须是IPosition
。制作IPosition
类型的参数,以便不允许来电者传入其他类型的对象(因为他们不会工作),并且您将能够从任何编译器错误,调用者传递的错误类型的对象。
请注意,一旦更改了参数,就不再有理由使该方法成为通用的,也不需要在方法体中强制转换参数。
答案 1 :(得分:2)
如果您的Position
类同时实施IPosition
,则只需
public static string PositionToCoordonates(IPosition position)
不需要泛型。
另一方面,如果这些类没有实现该接口(如果你创建了它就会出现这种情况),你将会有一些代码重复。
public static string PositionToCoordonates(Geolocation.Position position)
{
return PositionToCoordinates(position.Latitude, position.Longitude);
}
public static string PositionToCoordonates(Xamarin.Position position)
{
return PositionToCoordinates(position.Latitude, position.Longitude);
}
private static string PositionToCoordonates(double latitude, double longitude)
{
return string.Format(...);
}
作为对我答案第二部分的澄清:在C#中,类必须声明它们实现了一个接口,仅仅在该接口上定义了属性/方法是不够的。
因此,在您的示例中,position as IPosition
将为null
,(IPosition) position
将引发异常。
要使上述演员表工作,Position
必须声明为
class Position : IPosition
{
...
}
答案 2 :(得分:1)
因为你没有实现Positions
这两个void Main()
{
var position1 = new Position1() { Lat = 10, Lon = 5 };
var position2 = new Position1() { Lat = 12, Lon = 3 };
Console.WriteLine(GetLatLon(position1));
Console.WriteLine(GetLatLon(position2));
}
static string GetLatLon<T>(T input)
{
var position1 = input as Position1;
var position2 = input as Position2;
if (position1 != null)
{
return $"{position1.Lat}-{position1.Lon}";
}
if (position2 != null)
{
return $"{position2.Lat}-{position2.Lon}";
}
throw new ArgumentException(nameof(input));
}
class Position1
{
public double Foo { get; set ;}
public int Lat { get; set;}
public int Lon { get; set;}
}
class Position2
{
public int Lat { get; set; }
public int Lon { get; set; }
}
,所以你不能发明一个接口来使用它来进行强制转换。在这种情况下,我可能会按如下方式处理:
import random
input_list = [1, 3, "rand", 2]
def rand_replacer(my_list):
output_list = []
for item in my_list:
if item == "rand":
while True:
new_variable = random.randint(0, 4)
if new_variable not in my_list:
output_list.append(new_variable)
break
else:
output_list.append(item)
return output_list
对于只涉及2种可能类型的情况,动态似乎过于沉重。我不知道是否确实需要通用参数,但我希望能避免一次装箱/拆箱。