dynamic or object in C# - c#

I'm using a javascript dll in c# that evaluate a javascript scope.
For now, I always return the evaluated result by the javascript dll in a string.
However, I'm planning to change the way it's done. I created an enum DataType:
public enum DataType
{
Integer,
Decimal,
Boolean,
Text
}
So depending on the given datatype in a dropdownlist, I'm going to cast the result in an integer, decimal, boolean or text.
When I'm doing the cast, should I return a dynamic or an object of int, decimal, bool or string?
My understanding of the dynamic type is not that clear.

If what you want is to return a value whose type is determined at run time, and not at compile time, you should return dynamic. This will allow you to use the object in all appropriate types without C# giving you a compile time error, and possibly saving yourself from a few casting runtime errors caused by improper casts of object into a specific type.
public dynamic GetAnything(DataType dataType)
{
switch(dataType)
{
case Integer:
return 1;
case Decimal:
return 1.0;
case Boolean:
return true;
case Text:
return "1";
}
}
This will allow you to do:
var result = GetAnything(DataType.Text) + 1;
Without having to perform an explicit cast.
This is no more dangerous than returning an object, as you would do:
var result = (int)GetAnythingAsObject(DataType.Text) + 1;
Which would cause a runtime cast exception since object is in fact a string. Where as with dynamic, this will work for all types that support the + operator.
You can read more about the difference between object and dynamic in this msdn article: http://blogs.msdn.com/b/csharpfaq/archive/2010/01/25/what-is-the-difference-between-dynamic-and-object-keywords.aspx
Note: dynamic requires .Net 4 and over

No, dynamic types are for different usages. Use either an object or add generic calls for each enum type.

You don't have to return an object of a dynamic type.
You should use an object according to the selected data type.
The dynamic type is a type that will be checked at runtime, not during the compilation time. Typically, it's used for scenarios like dynamic API, COM API, Office API (Interoperability libraries). I don't see a reason for using it in your scenario.

Related

Difference between named field and named column in datatable

What is the difference bewteen the two below please?
var dtime = (DateTime)datatable[0]["SomeDateTime"];
var dtime = datatable[0].field<DateTime>("SomeDateTime");
EDIT
and this:
var dtime = Convert.ToDateTime(datatable[0]["SomeDateTime"]);
The difference is that the first uses an explicit cast by yourself whereas the second casts behind the scenes in the DataRow extension method Field.
So if the datetime-column can contain null-values you would use DateTime?:
DateTime? dtime = datatable.Rows[0].Field<DateTime?>("SomeDateTime");
So i would suggest to use Field. It's strongly typed(hides the cast) and supports nullable types. The explicit cast via (TypeName) is also less readable.
In the first line
var dtime = (DateTime)datatable[0]["SomeDateTime"];
you use the indexer property that returns an object. So you need to cast it yourself to the actual type you expect the object to be.
The second case
var dtime = datatable[0].Field<DateTime>("SomeDateTime");
calls the generic extension method Field<T> that tries to do the casting for you and returns the type you specified (so DateTime in your example).
You can inspect the different implementation in the reference source for the indexer and the Field<T>() extension method
The main difference between the examples given is the method of conversion
(Type) takes what ever type you have and forces it to become that type, erroring it not suitible
<Type> is passing in a generic type for the implementation of field to use in its typeless definition, which means that there is behind the scenes logic helping you convert
and Convert.ToType() is using the converter class to do the conversion, as its call required types to be compatible with the IConvertable interface this means someone has put some thought into making that type convertable which mean your likely to get a successful result
otherwise you are just using different means to access the named field (either the this property or the field method

Dynamically determine type to cast to (C#)

My function receives a parameter 'value', of type object. I want to assign it to a member of an object, but the cast doesn't happen implicitly, so I need to specify it explicitly. However, I don't want to actually specify the current type of that member in the object, so I could do this:
positiveOrder.OrderID = (int)value;
But, if business requirements change and OrderIDs are generated and stored in a different way, including a type change to Strings for GUIDS for example, I'll have to come back here and change it, which is undesirable cohesion. I've experimented with various permutations of code like
positiveOrder.OrderID = value as thisOrder.OrderID.GetType();
or
positiveOrder.OrderID = (typeof(thisOrder.OrderID)) value;
But nothing seems to be working. Any ideas on programatically specifying the type to convert to? It can be done at compile time or run time, since the Order class doesn't change.
If positiveOrder.OrderID will always be an integer (even if represented in a string), don't change the member to be anything but an integer. Instead, expose some method that can deal with different source types.
For example:
public void SetOrderID(object value)
{
this.OrderID = Convert.ToInt32(value);
}
See Convert.ToInt32().
Something like:
using System.Reflection;
receiver.GetType().GetProperty(propName).SetValue(receiver, value, null);

type casting in c#.net

i want to know typecasting in c# .net, i have below lines of code.
int i=4
object o = i // This works properly without any typecasting becausing boxing takes place automatically
string s= i // This does not work, even when the string is also reference type?
string s=(string)i //This also does not work even if i try to typecast the int to string.
string s= Convert.ToString(i); // this works.
so i want to know why string s = i and string s = (string)i does not work and whats the difference in using (string)i, i.ToString(), and Convert.ToString(i).
When it comes to boxing and unboxing, types have explicit and implicit casting. So, in some circumstances, it is easy enough for the runtime to allow for implicit conversion between two supported types, say an Int32 to a Double. However, there is no implicit or explicit conversion between an integer and a string, because obviously, a string is not an integer (despite the fact that a string can contain characters for an integer).
string s = i; // attempt at implicit cast from Int32 to String, error
object o = i; // all types inherit from Object, so you may implicitly or explicitly cast from Int32 to Object.
s = (string)i; // attempt at explicit cast from Int32 to string, error
s = i.ToString(); // conversion
s = Convert.ToString(i); // conversion
That's where Convert comes to play. Convert contains support for attempting to convert known primitives (and types supporting IConvertable) to another. So, ToString or Convert.ToString would be the preferred methods (ToString and Convert.ToString are virtually synonymous, except that ToString gives you some formatting options).
Well, string and object - both of them are reference types. However, object is a root type for all .NET types.
When you use such syntax as (string)i, you are trying to use explicit conversion beetween types. But this conversion type requires string class to know about all possible argument types.
So we have .ToString() method, which can be overriden in any class, and its return value is used as a string represenation of any object.
string s = i and string s = (string)i does not work
because I is not a string, and type CASTING is a CAST of the type, not a conversion. It only works if i contains a string or a subclass of string (which is not possible for strings, but may be for other classes).
whats the difference in using (string)i, i.ToString(), and Convert.ToString(i).
(string) i: cast i to a string, must be assignable.
i.ToString(): calls the ToSstring method, which is defiend on System.object, thus available on ALL classes and structs - but returns no sensible content if not overwritten.
Convert.ToString(i): coonverts i to a string. THis includes calling a converter which likely just calls ToString on this rare case.
At the end, casting is not aconversion. for (string) i to work i HAS TO BE A STRING, while convert tries to MAKE it a string.
You can specify implicit and explicit conversions in .net, the reason that string s = i fails is that there is no built in cast operation for an integer to a string.
see this MSDN article on casting for further information
string s= i does not work because the types don't match, int won't go into a string.
string s=(string)i does not work because it cannot asume which type conversion is to be used (i.e which base)
something like s = ""+i would work on the other hand as it would asume base 10 conversion.
so i want to know why string s = i and string s = (string)i does not work
The short answer is that there is no implict (first example above) nor explicit (second example above) cast from int to string defined. Slightly longer answer; when authoring the struct Int32 in C# no casting behaviour was programmed to enable the developer to automagically cast from an int to a string
whats the difference in using (string)i, i.ToString(), and Convert.ToString(i)
Well, the first doesn;t work as you said, and as ive explained above. The second calls the ToString method on the struct Int32, which returns (as the name implies) a string representation of the object. It should be noted that this is a brand new string, not in any way related to the original value. The third example Convert.ToString will, under the hood, call whatever the most appropriate way to turn the parameter passed in to a string - most likely just calls the ToString method - so pretty much identical to example 2.
ToString() method is override by each referance which is vitual method in the object class. string calss override that method and provide string value out of this.
The default implementation of the ToString method returns the fully qualified name of the type of the Object, as the following example shows.
Object obj = new Object();
Console.WriteLine(obj.ToString());
// The example displays the following output:
// System.Object
this behavior is inherited by reference types that do not override the ToString method.
Typecasting in C# only works along the lines of class inheritance. Object is the root of all types in C# and therefore all values can be typecast to it.
string and int do not share the same branch of inheritance and so cannot be directly cast from one to the other.
Convert.ToString() is a method designed to convert an integer to a string - there's no typecasting going on, it's just executing a method designed to convert an integer to a string representation.
i.ToString() performs the equivalent functionality to Convert.ToString(), except that i.ToString() has overloads which allow greater flexibility on the representation of the number in string format.
One last note, exceptions to the typecasting rules can be included by the developer by using a public static explicit operator method which permits the developer to convert one value to another as they see fit.
First thing to note is that every class derives from object.
Casting int to object is using an Int32.
Casting string to object is using a String.
There is no implicit cast from an integer to a string because they are in different parts of the class hierarchy - one does not in any way relate to another. However because string is used so often for output object (and therefore all its children) have a ToString() method for convenience.
However Convert is written specifically to be able to convert from one type to another, for example Convert.ToBool(x) can parse "true" or "false" to boolean, and as you have shown it can convert an integer to a string - again this is really a convenience that probably just calls Int32.ToString() under the hood.

Determining the expected type of a DynamicObject member access

Is it possible to determine what type a dynamic member access expects? I've tried
dynamic foo = new MyDynamicObject();
int x = foo.IntValue;
int y = (int)foo.IntValue;
And in the TryGetMember intercept GetMemberBinder.ReturnType is object either way. I also implemented TryConvert wondering if it might get invoked to do the conversion, but it never is hit.
Is there some other override I'm missing that lets me determine what Type the caller wants so that I can do the appropriate conversion?
In C#, when using dynamic, the compiler always sets the binder to return type of object, and then does a second dynamic implicit conversion to the expected return type. So on a DynamicObject when called from c#, GetMemberBinder.ReturnType will always be object, but that said if you return another sort of springboard dynamic object with TryConvert implemented you could get that type, except if the user does var or dynamic as the variable, then they have a proxy that won't do anything until it becomes statically typed.
ImpromptuInterface does something different but along these lines, because it also has the desire to have a dynamic implementation that changes based on return types -- just you would have to describe the dynamic object via an interface.

Object to System.String implicit conversion

I have a question regarding type conversion in C#.
Object data_obj = "test";
string data_str;
data_str = data_obj;
this produces an error claiming no implicit conversion exists. Now, this is, at least for me, a little bit unintuitive, since Console.WriteLine("type{0}",data_obj.GetType()) produces System.String, but then again, i am really new at C#.
Now, getting past this, i would like to cast to the type of the data stored in data_obj, without having to switch and selecting the type manually.
So, basically, what i am asking is: is there a way to define an implicit conversion from System.Object to System.String, System.Decimal, etc.
Context:
I am reading from an ODBC connection to an SQLServer database and trying to pump those rows into an Oracle Database. Now, the correspondence of SQLServer and Oracle rows have to be defined. Now, i read the data from the SQLServer table with no problem whatsoever, and i store it in a List<Dictionary<string,Object>> (i know, storing the rows seem wrong, but design requirements, what can you do).
The insertion part is where i am having problems with the insertion. I basically loop (with a foreach) through the elements of the list and insert them row by row. It is here where i need to determine the type of the data stored in the Object.
Edit: Including a bit more detail.
No, there's no way of doing it implicitly. Options:
Call ToString() explicitly (which will throw an exception if the reference is null)
Call Convert.ToString()
Use "" + data_obj (ick, don't do it)
Cast if you're sure that data_obj is really a string
Why are you so keen on an implicit conversion though?
What you should be doing in your code as noted above is casting, not converting. The object in question is a string; you simply have stored it in an object reference.
Casting would be done like so:
data_str = (string)data_obj;
The overload of Console.Writeline you are mentioning takes a format string, and then a params array of object... not strings. It calls ToString() on each of those objects. So your call to data_obj.GetType().ToString() could be slimmed down to data_obj.GetType() (calling ToString() on a string just returns the string again)
As for an implicit conversion from object to type x... think about what you are asking; a reference of object can be any CLR type. How do you handle those conversions?
You could use the Convert.ToString method:
object o = ...
string s = Convert.ToString(o);
There is no implicit conversion from object to string in C#. However you could call the object's virtual ToString method
string s = o.ToString();
If you store your value in a var instead of type object and let the compiler decide what the value is, then it can be made implicit.
var data_obj = "test";
string data_str;
data_str = data_obj;

Categories