我将问题简化为一个小程序,该程序举例说明了我在运行时收到的确切错误。
您可以将其复制粘贴到控制台应用程序中,然后自己查看。
using System.Collections.Generic;
namespace ConsoleApplication5
{
class Program
{
static void Main(string[] args)
{
var list = new List<MyDataClass>()
{
new MyDataClass {A = 1, B = 1},
new MyDataClass {A = 3, B = 8}
};
var ops = new MyOperationsClass();
ops.ReallyGreatOperation(list, list[0]);
}
}
public class MyDataClass
{
public int A { get; set; }
public int B { get; set; }
public void AddDataPartsToEachOther()
{
var c = A + B;
A = c;
B = c;
}
}
public class MyOperationsClass
{
public void ReallyGreatOperation(object obj, object z)
{
dynamic x = obj;
if (x.Contains(z)) //<-- gets an error here..
((dynamic)z).AddDataPartsToEachOther();
}
}
}
那么到底是什么问题呢?
据我了解,
dynamic
关键字可以用作通配符,如果存在方法,则可以毫无问题地调用它。那么为什么在这种情况下对我不起作用?现在,我知道可以通过执行以下操作将其更改为工作:
public class MyOperationsClass
{
public void ReallyGreatOperation(object obj, object z)
{
dynamic x = obj;
// if (x.Contains(z)) //<-- gets an error here..
// ((dynamic)z).AddDataPartsToEachOther();
if (x.GetType().GetMethod("Contains").Invoke(obj, new[] {z}))
((dynamic)z).AddDataPartsToEachOther();
}
}
但是正如我说的那样-我希望能理解为什么更“自然”的方式不起作用..原因是如果我选择第二种方式-我看不出语言中
dynamic
的意义不再。收到的实际错误:
System.Core.dll中发生了类型为“ Microsoft.CSharp.RuntimeBinder.RuntimeBinderException”的未处理异常
附加信息:'System.Collections.Generic.List.Contains(ConsoleApplication5.MyDataClass)'的最佳重载方法匹配具有一些无效的参数
对于那些可能认为与之相关的人,我添加了一段我的实际代码:
case RelationNavigation.RelationNavigationMultiplicity.ManyToOne:
{
var stringValue = dto.PropertiesData[relationNavigation.PropertyEnd.PropertyInfo.Name];
if (string.IsNullOrEmpty(stringValue))
continue;
dynamic list = relationNavigation.PropertyEnd.PropertyInfo.GetValue(modelObj);
var relatedModelIds = stringValue.Split(',').Select(int.Parse).ToArray();
foreach (var relatedModelId in relatedModelIds)
{
var relatedModel = GetById(relationNavigation.PropertyEnd.RelatedType, relatedModelId);
if (relatedModel == null)
continue;
if(!list.GetType().GetMethod("Contains").Invoke(list, new[] { relatedModel }))
//if (!list.Contains(relatedModel))
list.Add(relatedModel);
relationNavigation.RelatedObjectPropertyEnd.PropertyInfo.SetValue(relatedModel, modelObj);
}
break;
}
谢谢。
最佳答案
代替
if (x.Contains(z))
您需要将
z
强制转换为dynamic
:if (x.Contains((dynamic)z))
有关为什么需要这样做的更多信息,请参见此处:Method not being resolved for dynamic generic type,我认为这个问题是重复的。
也就是说,使用
dynamic
通常是不好的设计。通常,使用泛型和/或接口是一种更好的方法。关于c# - 从C#动态类型调用`Contains`方法会产生错误-为什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37582482/