我将问题简化为一个小程序,该程序举例说明了我在运行时收到的确切错误。

您可以将其复制粘贴到控制台应用程序中,然后自己查看。

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/

10-09 07:30
查看更多