Passing dynamic object to C# method changes return type
This is because almost any operation involving a dynamic value is resolved dynamically at execution time. There are no exceptions made for cases where actually there's only one method present at compile-time; the language is simpler that way. (For certain calls, the compiler does perform enough resolution at compile-time to ensure that there is at least one method with a suitable number of parameters - this is specified in the C# 5 spec in section 7.5.4, but that doesn't affect the effective return type.)
From the C# 5 spec, section 7.6.5:
An invocation-expression is dynamically bound if at least one of the following holds:
- The primary-expression has compile-time type
dynamic
.- At least one argument of the optional argument-list has compile-time type
dynamic
and the primary-expression does not have a delegate type.
In this case the compiler classifies the invocation-expression as a value of type
dynamic
. [...]
There are a few operations involving dynamic values which still have a non-dynamic overall type. For example:
d is Foo
is alwaysbool
d as Foo
is alwaysFoo
new Foo(d)
is alwaysFoo
even though the exact constructor to use is determined at execution time
But any method call is treated as having a return type of dynamic
.
Dynamic method return type in C#
As far as I understand the problem, you need to return a more complete data when the retriever is the admin, and a not-so-complete one when not.
If that is the objective, then you can retrieve the appropriate data from the database and fill in an object of one of the following classes:
public class PersonData {
public string Name { get; private set; }
public string Surname { get; private set; }
}
public class ExtendedPersonData: PersonData {
public string Name { get; private set; }
public string Surname { get; private set; }
public string Address { get; private set; }
}
Since the latter class inherits from the former, you can just create a List<PersonData>
and that will cover both cases.
Another, different approach: the data class takes into account the user in order to return or not certain data:
class Person {
public Person(User usr, string address)
{
this.User = usr;
this.address = address;
}
public string User { get; private set; }
public string Name { get; private set; }
public string Surname { get; private set; }
public string Address {
get {
string toret = "N/A";
if ( this.User.IsAdmin() ) {
toret = this.address;
}
return toret;
}
}
private string address;
}
Neither of both solutions is perfect, and both have their own issues, but the problem, at least how you stated it, cannot be solved.
Hope this helps.
Generic method return dynamic for unknown reason
Almost everything you do with a value of type dynamic
results in a value of dynamic
. Sure, you know the return type of the TryConvertToEnum
method you intend to call - but you're passing in a dynamic argument, which means it's not bound until execution time. At execution time, there could be a whole other method with a string
parameter and a different return type.
There are a very few cases of expressions which include dynamic values but still don't have a result type of dynamic
. Off the top of my head, they are:
- Constructor calls (always the type being constructed)
- The
is
operator (always bool) - The
as
operator (always the type named as the second operand)
In your case, just use object
instead of dynamic
and the call will be statically bound instead, and value
will be of type MyEnum?
.
How to return dynamic return types in methods? C#
You're solving the wrong problem. If you have a superclass A
, with subclasses B
, C
, etc., that all have similar functionality, you want to do the following:
Make
A
an interface thatB
,C
, etc. implement. Code that works withB
orC
instances does by working through the interface provided byA
. If you can define a common set of operations that work on all the types, then this is all you need to do.If you can't define a common set of operations, e.g. you have code similar to:
A foo = GetA();
if(foo is B) {
B bFoo = (B) foo;
// Do something with foo as a B
} else if(foo is C) {
C cFoo = (C) foo;
// Do something with foo as a C
} ...Or even this (which is basically the same thing, just using extra information to emulate what the type system already provides for you):
A foo = GetA();
MyEnum enumeratedValue = foo.GetEnumeratedValue();
switch(enumeratedValue) {
case MyEnum.B:
B bFoo = (B) foo;
// Do something with foo as a B
break;
case MyEnum.C:
C cFoo = (C) foo;
// Do something with foo as a C
break;
}Then what you really want is to do something like:
A foo = GetA();
foo.DoSomething();Where each subclass would implement the corresponding branch of the
switch
statement. This is actually better in several ways:- It uses less overall code.
- Since the implementations of the cases live in the various implementation classes, no casting is necessary; they can access all the member variables directly.
- Since you're not building a big
switch
/case
block separate from the actualB
andC
implementations, you don't run any risk of accidentally forgetting to add a correspondingcase
if add a new subclass. If you leave theDoSomething()
method out of a subclass ofA
, you will get a compile-time error.
Edit: In response to your comment:
If your DoSomething()
routine needs to operate on a Form
or other GUI element, just pass that element into the method. For example:
public class B : A {
public void DoSomething(MyForm form) {
form.MyLabel.Text = "I'm a B object!";
}
}
public class C : A {
public void DoSomething(MyForm form) {
form.MyLabel.Text = "I'm a C object!";
}
}
// elsewhere, in a method of MyForm:
A foo = GetA();
foo.DoSomething(this);
Alternatively, an even better idea might be to turn your B
and C
classes into custom controls, since they seem to encapsulate display logic.
Dynamically create or set the return type of a function in the function
The only possible way for the consumer of such a method to actually rely on the fact that the return type is dynamic is if, at least for that one method call, the return type is statically known at compile time.
There is a specific feature for a method that has some type unknown at the time the method is written, but fixed when a particular call to that method is make. That feature is called "generics".
public T Foo<T>()
where T : new()
{
return new T();
}
That's really the only available option for a truly dynamic return type that has much potential for really being useful.
If that's not what you want, or that is not a workable option for you, then odds are pretty high your method shouldn't have a dynamically changing return type. Instead it should have a fixed return type of some more generalized type that can have multiple implementations. Generally this would mean an interface, to which you can return one of any number of possible implementations. This should be done if the caller doesn't need to really know or care what the implementation is, but rather all they need to know is that they are given some implementation of an interface that exposes all of what they need. In your case, perhaps something like Control
would be workable, if the caller only need to know that they are given some type of control, and to which the API of Control
provides everything that they need to do with it.
Method declared with dynamic input parameter and object as return type in fact returns dynamic
The problem is that you're calling a method with a dynamic
argument. That means it's bound dynamically, and the return type is deemed to be dynamic. All you need to do is not do that:
object dObj = "123";
var obj = Convert(dObj);
Then the Convert
call will be statically bound, and obj
will have a type of object
.
From the C# 5 specification, section 7.6.5:
An invocation-expression is dynamically bound (§7.2.2) if at least one of the following holds:
- The primary-expression has compile-time type dynamic.
- At least one argument of the optional argument-list has compile-time type dynamic and the primary-expression does not have a delegate type.
In this case the compiler classifies the invocation-expression as a value of type
dynamic
.
Dynamic arguments and return type
You cannot call extension methods on object of type dynamic
. Extension methods are a purely compile time construct. At runtime, it will search for an instance method called FirstOrDefault
, not find one, and therefore error out.
Your solutions are to either cast the result of Query
to the appropriate type before calling FirstOrDefault
on it, or to not use the extension method syntax and instead write out: Queryable.FirstOrDefault(Query<T>(...))
which will tell the runtime binder that it's trying to bind the result of Query
to the appropriate static method, rather than an instance method.
As for why any method accepting arguments of type dynamic
always resolves to an expression of type dynamic
: that's simply what the specs say to do. The whole point of using dynamic
is to defer binding of the methods until runtime, so it cannot be sure of what the value of that expression will be until runtime; to get around that, it needs to propagate the dynamic
type.
Why does a method that returns a type result in an implicit typing of dynamic?
Why does a method that returns a type result in an implicit typing of dynamic?
Because that's the best the compiler can do, given the information it has.
The reason methodResult
is dynamic
is that the entire expression used to initialize it is dynamic
. And that's the case, because data
is dynamic.
When you use dynamic
, you're telling the compiler to not resolve types at compiler time. Instead, they should be resolved according to the normal compiler rules, but at run-time.
The fluentClass
variable could hold some implementation of FluentClass
that contains an overload that matches the run-time type of the argument data
. In that case, a different implementation of SomeMethod()
could be called, returning a different type.
You've told the compiler to defer type resolution to run-time, so it can't force things back into a strongly-typed context unless you tell it explicitly what type things are. In your example, it can't, so the type remains dynamic
.
Note that you might have thought that the compiler would identify the one overload you've provided, based on its parameter type of dynamic
. But that's not how dynamic
works. The dynamic
parameter affects only the implementation of the method, i.e. the code in its body. As far as calling the method goes, the parameter is essentially object
. It's just that when the parameter value is used in the method body, it has the features of dynamic
.
Another way to think of dynamic
is that it accepts any object as input (like object
), but then allows you to use any member of that object that you believe exists (if it doesn't exist an exception will be thrown at run-time). Using dynamic
defers the compiler logic downstream, i.e. for the output of any usages of the dynamic
variable, but doesn't affect the input, i.e. the assignment of that variable.
Note also that even if the method call is completely unambiguous, e.g. a static
method where there's only one method with that name, you'll still get a dynamic
result. Once you start using dynamic
, it sticks with you until you provide an explicit cast to get back to a known type.
Related reading:
Very similar to your question, if not actually duplicates:
Why does a method invocation expression have type dynamic even when there is only one possible return type?
Why does this method keep returning dynamic despite the return type in the signature?
Why doesn't this string.Format() return string, but dynamic?
More general discussion of dynamic
:
What is the 'dynamic' type in C# 4.0 used for?
C# 4: Real-World Example of Dynamic Types
Passing an instance of a dynamic type to a generic method in a generic class
To answer your question:
var type = typeof(abc);
object instanceToModify = new abc();
var typeToCreate = typeof(GenericClass<>).MakeGenericType(type);
var methodToCall = typeToCreate.GetMethod("GenericMethod");
var genericClassInstance = Activator.CreateInstance(typeToCreate);
methodToCall.Invoke(genericClassInstance, new[] { instanceToModify });
DEMO
But:
If your type is only known at runtime your instance must be handled in a variable declared as object
or dynamic
. In that case you can change your method signature to:
public object GenericMethod(object obj)
{
// modify the object in some (arbitrary) way
IEnumerable<FieldInfo> fields = obj.GetType().GetRuntimeFields();
foreach (var field in fields)
{
if (field.FieldType == typeof(string))
{
field.SetValue(obj, "This field's string value was modified");
}
}
return obj;
}
There's no need for a generic class/method.
Related Topics
Is There a Faster Way to Scan Through a Directory Recursively in .Net
How to Get First Record in Each Group Using Linq
Injecting Dependencies into ASP.NET MVC 3 Action Filters. What's Wrong with This Approach
How to Style Chat Window Using CSS When Using Microsoft Bot Framework
How to Add Js and CSS Files in ASP.NET Core
Style Bundling Not Working After Iis Deployment (MVC 4)
How to Get My C# Program to Sleep for 50 Msec
How to Use Jwt in MVC Application for Authentication and Authorization
Difference Between Casting and Using the Convert.To() Method
C++/Cli Wrapper for Native C++ to Use as Reference in C#
What Are the Definitions for Lparam and Wparam
Pass C# String to C++ and Pass C++ Result (String, Char*.. Whatever) to C#
How to Get a JSON String from Url
How to Write Fast Colored Output to Console
How to Represent a Time Only Value in .Net
Why Do I Get an Outofmemoryexception When I Have Images in My Listbox