.net - Calling `Contains` method from C# dynamic type yields error - why? -
i simplified problem tiny program examples exact error receive during run-time.
you can copy-paste console application , see yourself.
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 { get; set; } public int b { get; set; } public void adddatapartstoeachother() { var c = + b; = c; b = c; } } public class myoperationsclass { public void reallygreatoperation(object obj, object z) { dynamic x = obj; if (x.contains(z)) //<-- gets error here.. ((dynamic)z).adddatapartstoeachother(); } } }
so problem?
as understand dynamic
keyword can used wildcard, if method exists called no problem. why not working me in scenario?
now, know can change work doing this:
public class myoperationsclass { public void reallygreatoperation(object obj, object z) { dynamic x = obj; // if (x.contains(z)) //<-- gets error here.. // ((dynamic)z).adddatapartstoeachother(); if (x.gettype().getmethod("contains").invoke(obj, new[] {z})) ((dynamic)z).adddatapartstoeachother(); } }
but said - wish understand why more "natural" way not working.. cause if 2nd way out of no choice - don't see point of dynamic
in language anymore.
the actual error received:
an unhandled exception of type 'microsoft.csharp.runtimebinder.runtimebinderexception' occurred in system.core.dll
additional information: best overloaded method match 'system.collections.generic.list.contains(consoleapplication5.mydataclass)' has invalid arguments
for may find relevant add snippet of actual code:
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; }
thanks.
instead of
if (x.contains(z))
you need cast z
dynamic
:
if (x.contains((dynamic)z))
for more information on why needed, see here: method not being resolved dynamic generic type, think question duplicate of.
that said, using dynamic
bad design. there better way using generics and/or interfaces.