不调用隐式转换

本文关键字:转换 调用 | 更新日期: 2023-09-27 18:04:02

我有两个对象:ObjObjViewModelObjViewModel内部有一个方法,看起来像这样:

public static implicit operator ObjViewModel(Obj o)
{
  //Code to do the conversion here
}

我后来有一个反射方法,最终遇到了需要将List<obj>复制到List<objViewModel>的情况。代码看起来像这样:

foreach(var p in propertyPairs)
{
  if (p.ViewModel.PropertyType.GetInterfaces().Count(i => i.Name == "IList") > 0)
  {
    p.ViewModel.SetValue(ret, Activator.CreateInstance(p.ViewModel.PropertyType));
    foreach (var v in (IList)p.Model.GetValue(m))
    {
      ((IList)p.ViewModel.GetValue(ret)).Add(v);
    }
  }
  else
    p.ViewModel.SetValue(ret, p.Model.GetValue(m));

问题是,当我到达((IList)p.ViewModel.GetValue(ret)).Add(v);时,隐式转换从未在v上调用,代码崩溃,因为v是obj类型,列表正在寻找objViewModel。有人知道怎么解决这个问题吗?

不调用隐式转换

您有一个编译时类型(由于强制转换)非泛型IList的表达式。非泛型IListAdd方法采用System.Object。所以:

((IList)something).Add(v);

只需要将v转换为System.Object。因此c#编译器不会插入对用户定义转换的调用。

即使转换为implicit,您也可以显式调用它,如:

((IList)something).Add((ObjViewModel)v);

另一种可能的工作(我不确定你在后台有什么类型)是:

((IList<ObjViewModel>)something).Add(v);

要求something实际实现IList<ObjViewModel>。这个Add方法是另一个接受ObjViewModel类型参数的方法,因此c#编译器将搜索并找到您的用户定义转换并发出在v上调用它的IL代码。