Dynamic type in method parameter - c#

I am passing in a dynamic type into a method and having some issues running the code. Wondering if you are able to pass a dynamic object into as a parameter using the out keyword.
Below is the code.
dynamic btApp = AutomationFactory.CreateObject("Test.Application");
dynamic btMessages;
dynamic btFormat = btApp.Formats.Open("c:\\Temp/Format1.btw", false, "");
btFormat.SetNamedSubStringValue("testing", "testtest");
btFormat.Print("Job1", true, -1, out btMessages);
btFormat.Close(2);
issue is in the print method. where the last argument is passing in a dynamic object.

When you pass a out parameter to a method with a variable that is of type dynamic the parameter itself must be of type dynamic. The following code is legal:
class Program {
static void Main(string[] args) {
dynamic value;
SomeMethod(out value);
return;
}
static void SomeMethod(out dynamic value) {
value = "5";
return;
}
}
In fact SomeMethod can assign anything to value. When the parameter is not of type dynamic then the compiler attempts to convert before the method call, which is not permitted, so if the parameter in SomeMethod is anything but dynamic, your out of luck.

It depends on what the actual type signature of the Print method is. The dynamic type is represented as object at runtime, so if the Print method takes an out parameter of type object (or dynamic), then it should work.
If the Print method has actual out parameter of some other type, then the actual runtime type used at the side of the caller doesn't match the actual type of the declaration, so it will not work.

Related

Why can't I convert from 'out BaseClass' to 'out DerivedClass'?

I just learned that having a generic argument as the type of an out parameter forces that generic type to be invariant. This is surprising to me. I thought out parameters are treated the same as return types (i.e. if the generic parameter is covariant, then it can be used in as an out out parameter), since they are both "outputs" of a method.
After a bit of investigation, I realised that you can't do this:
public class Program {
public static void Main() {
// cannot convert from 'out object' to 'out string'
F(out object s); // passing an out object
}
public static void F(out string o) {
o = null;
}
}
This explains why out parameters must be invariant. However, I still don't understand why you can't do this. As is commonly known, out parameters are just another way of returning a value. F could be rewritten with a return value, and it will work:
// This is the semantically equivalent version of the above, just without "out"
public class Program {
public static void Main() {
object s = F();
}
public static string F() {
return null;
}
}
So why doesn't the first code snippet compile? Does using out allow F to do something that can't be done with return values, that will break type-safety if an out object s were passed to it?
I found this question, which is about converting the other way - from a derived class to a base class, which clearly isn't possible. You can't assign the return value of a method that returns a object to a variable of type string, can you?
What I'm asking is, since you can assign the return value of a method that returns string to a variable of type object, why can't you do the same with out parameters? That is, why can't you pass an out object to a out string parameter?
I also read the docs and the spec, but they never mentioned anything about the fact that you have to pass the exact same type into a out parameter, let alone explain why you have to do it.
With out parameters the argument is passed by reference just like ref, the difference is that the value must be assigned by the end of the method and the reference does not need to be initialized before calling. But it can be initialized before and the method can read the initial value.
From the docs: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out-parameter-modifier
The out keyword causes arguments to be passed by reference
It is like the ref keyword, except that ref requires that the variable be initialized before it is passed
As the method can read the variable, the reference must be of type string to work. The reading blocks covariance and the output blocks contravariance, thus the argument must be invariant.
As is commonly known, out parameters are just another way of returning a value
Not true: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out
As a parameter modifier, which lets you pass an argument to a method by reference rather than by value.
That means that you are passing on a reference to a specific object.
I think your answer though is here: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref
Passing a reference type by reference enables the called method to replace the object to which the reference parameter refers in the caller.
So when you are passing an object to the function you are effectively doing an assignment of type
derived <- base
and when you are assigning from inside the function
base <- derived
Think about that you can do something like this in c#:
public static void Out(out string s)
{
Thread.Sleep(50);
s = "World";
}
public static void Ref(ref string s)
{
Console.WriteLine(s); // Hello
Thread.Sleep(100);
Console.WriteLine(s); // World
}
string str = "Hello";
new Thread(() => Out(out str)).Start();
new Thread(() => Ref(ref str)).Start();
If it is legal to change string str to object str, now str can be any type, how to keep the reference between Out and Ref method?

C# using an object as an Type in SQLite for UWP

I'm trying to make one function that can take an object as a parameter
public static List<T> Get_DataList_DataFromSystem<T>(object DataNeeded, string BaseTypeString)
{
Type baseType = DataNeeded.GetType();
SQliteConnector.GetInstance.conn.Table<baseType>();
}
using SQliteConnector.GetInstance.conn.Table(); i want to able to use the parameter DataNeeded that is passed into the function.
SQliteConnector.GetInstance gets an instance of the (SQLiteConnection( new SQLitePlatformWinRT(), path );)
SQliteConnector.GetInstance.conn.Table(); requires a class to be passed in
Generic methods require the type to be known at compile time, whereas GetType() is executed at runtime.
This is what you're after:
public static List<T> Get_DataList_DataFromSystem<T>(T DataNeeded, string BaseTypeString) where T : class
{
SQliteConnector.GetInstance.conn.Table<T>();
}
The type of DataNeeded can then be inferred at compile time, based on the type of object that is passed to the method.

C# generics: Can you convert <T> ToString?

Quick one here~
I want to convert < T > ToString so I can replace the variable with that type~
public void ChangePanel<T>(T Action){
FieldInfo Field = T.GetField(T.toString);
Field.SetValue(SomeObject, Action);
}
Also please let me know if there is a better way to do this!!
Edit: FYI the variables in SomeObject have the same name as type
You can use the typeof Keyword to get a Type instance, and the Type.Name Property to get the type's name.
public void ChangePanel<T>(T action)
{
Type typeOfObject = someObject.GetType();
Type typeOfAction = typeof(T);
FieldInfo field = typeOfObject.GetField(typeOfAction.Name);
field.SetValue(someObject, action);
}
Yes. ToString() is defined on the object class which everything derives from so I would expect you can call it on any type T. However, you need to call it on the parameter itself, not the type, so rather than doing T.ToString() you should be doing Action.ToString(). If you want to get the name of the type then you should use reflection rather than ToString.
Also, the reflection options are either;
typeof(T).Name
or
Action.GetType().Name
If you want to get the name of a generic type, then you can simply call typeof(T).Name:
public static string GetGenericTypeName<T>()
{
return typeof(T).Name;
}
The ToString method is a method, so you need parentheses to call it, and the case is important for identifiers:
FieldInfo Field = (typeof T).GetField(Action.ToString());
The GetField is a method of the Type class, so you need typeof to get the Type object for the T generic type.

How does generic type inference work in C#?

If I have the following code
private BaseMessage getMessage()
{
return new OtherMessage();
}
private void CheckType<T>(T type)
{
Console.WriteLine(type.GetType().ToString());
Console.WriteLine(typeof(T).ToString());
}
private void DoChecks()
{
BaseMessage mess = getMessage();
CheckType(mess);
}
why do I get different types outputted? Is there anyway of getting the type inference to use the actual type of the object being passed?
Generic type inference means that the compiler automatically resolves the types of the arguments being passed without the need of you explicitly specifying what type you're passing. This means that this is done in compile-time: in your code, during the compilation, the compiler only knows about BaseMessage, so the parameter will be passed as BaseMessage. During the run-time, the parameter's actual type will be OtherMessage, but that is of no concern to the compiler.
Therefore, the output you're getting is absolutely valid. I don't know any ways do overcome this issue, apart from always using Object.GetType instead of typeof().
The reason is that you've declared the variable mess as being of type BaseMessage. So when you ask for the type, it's returning BaseMessage.
It's a difference between the way that GetType and typeof behave. GetType returns the actual type of the object at run-time, which can be different from the type of the variable that references the object if inheritance is involved (as is the case in your example). Unlike GetType, typeof is resolved at compile-time to a type literal of the exact type specified.
public class BaseMessage { }
public class OtherMessage : BaseMessage { }
private BaseMessage getMessage()
{
return new OtherMessage();
}
private void CheckType<T>(T type)
{
Console.WriteLine(type.GetType().ToString()); // prints OtherMessage
Console.WriteLine(typeof(T).ToString()); // prints BaseMessage
}
private void DoChecks()
{
BaseMessage mess = getMessage();
CheckType(mess);
}
You have to choose the right tool for the job. Use typeof when you want to get the type at compilation time. Use GetType when you want to get the run-time type of an object.

.NET Generics: Using an Activator created type as a generic shows wrong Type? Need workaround

This really has my stumped today. I'm sure its simple, but... Here is my sample code:
using System;
using System.Collections;
namespace ConsoleApplication1
{
class Program
{
public ArrayList SomeProp { get; set; }
static void Main(string[] args)
{
// Get the Type of a property by reflection.
Type myPropType = typeof(Program).GetProperty("SomeProp").PropertyType;
// Create an instance of the determined Type.
var x = Activator.CreateInstance(myPropType);
// Now try to use that instance, passing to a method that takes a generic.
WhatAmI(x);
Console.ReadKey();
}
private static void WhatAmI<T>(T x)
{
Console.WriteLine("T is: " + typeof(T).FullName);
Console.WriteLine("x is: " + x.GetType().FullName);
}
}
}
The output here is:
T is: System.Object
x is: System.Collections.ArrayList
Basically what is going on here is I have some property on some class. It doesnt really matter what/where that comes from. The important part is that I get the PropertyInfo for that property. From there I create a new instance of its Type with Activator.
Now If I pass that created instance to a function that takes a generic parameter, the generic Type always comes across as Object, because Activator.CreateInstance() returns an Object, so "var x" is an Object, not, in this case, an ArrayList.
What I need to happen is for the generic type to be the actual type, int his case "ArrayList".
I know there is an Activator.CreateInstance() that I can use instead, but I can't use a Type (PropertyInfo.PropertyType) within the angle brackets for that method.
I could also just cast the returned object, like:
myPropType x = (myPropType)Activator.CreateInstance(myPropType);
But obviously that doesn't compile... Plus it wouldn't be valid anyway because the cast is compile time, and I don't know the type until runtime, but conceptually its what I need...
So I'm stuck with this Type, but I can't figure out how to get it passed over to the WhatAmI() method, and have T be ArrayList, not Object.
Ideas?
To call generic methods using a Type at runtime, you need to use reflection - and MakeGenericMethod in particular, something like:
typeof(Program).GetMethod("WhatAmI",
BindingFlags.Static | BindingFlags.NonPublic)
.MakeGenericMethod(x.GetType()).Invoke(null, new object[] { x });
Otherwise, the compiler infers the <T> from the variable type - object in this case.
One side point here is that you can improve things by only doing the reflection once - i.e. don't use Activator, but use a generic constraint instead:
private static void WhatAmI<T>() where T : new()
{
T x = new T();
Console.WriteLine("T is: " + typeof(T).FullName);
Console.WriteLine("x is: " + x.GetType().FullName);
}
Defines the method without an arg, but with a default constructor; then:
// Get the Type of a property by reflection.
Type myPropType = typeof(Program).GetProperty("SomeProp").PropertyType;
// Now call a generic method just using the type
typeof(Program).GetMethod("WhatAmI",
BindingFlags.Static | BindingFlags.NonPublic)
.MakeGenericMethod(myPropType).Invoke(null, null);
calls the method just using the type - the instance is created inside the method. This is usually faster than repeated reflection.

Categories

Resources