Convert reference primitives to generic type - c#

I know the title is confusing so I'll try to explain better. Here's basically what I want to do inside a method:
if (record["id"] != DBNull.Value) _id = Convert.ToInt32(record["id"]);
else id = -1;
I want this to work for multiple types that I have stored in my database. (So if it's a string it converts it to a string and so forth). Any way to do this is fine, and I was trying to do it with a method. I got this far but C# won't automatically convert int to object. ideas?
private void Load(ref object var, object obj, object def)
{
if (var is int)
{
var = Convert.ToInt32(obj);
}
}
int _id;
Load(ref _id, record["id"], -1);
Just to clarify, my error is "cannot convert from ref int to ref object".
Thanks for any help.

You can use Convert.ChangeType() and make your method generic:
private void Load<T, U>(out T value, U obj, T defaultValue)
{
if (obj is DBNull)
value = defaultValue;
else
value = (T)Convert.ChangeType(obj, typeof(T));
}
Now you can just use it like this (simplified example, not sure what you need def for):
int id;
object foo = 42;
Load(out id, foo, 1);

First off, var is a reserved word in C# 3.0 and above (VS 2008 and later).
More to the point, I'd try setting this up as a generic; that way, your method can discover the true types of the variables you pass in, and work with them case-by-case as if they were strongly typed:
private void Load<TVar, TSet>(ref TVar var, TSet obj, TVar def)
{
//this is a little heavy-handed, but in pretty much any situation where
//this can fail, you just want the basic type.
try
{
if (var is IConvertible && obj is IConvertible)
var = (TVar)Convert.ChangeType(obj, typeof(TVar));
else
var = (TVar)obj; //there may just be an explicit operator
}
catch(Exception)
{
var = def; //defined as the same type so they are always assignable
}
}

Related

How to access methods of subclass in object array C#?

How can I set/get the value of an object in an object array?
Currently I get:
"object does not contain a definition for 'value' and no extension method"
Example C#;
public class myObjClass
{
public int value = 5;
}
public class myObjClass2
{
public float[] pos = new float[2];
}
public void test()
{
myObjClass myObj = new myObjClass();
myObjClass2 myObj2 = new myObjClass2();
object[] objArr = new object[2];
objArr[0] = myObj;
objArr[1] = myObj2;
Debug.Print(myObj.value.ToString());
Debug.Print(objArr[0].value.ToString()); // how?
}
Its because a generic object does not have the property value your class myObjClass has. To fix this you could cast the item to your class like so:
((myObjClass)objArr[0]).value.ToString()
Only do this ^ if you are sure of the type
Instead you could also check it first:
With as:
var item = objArr[0] as myObjClass;
if( item != null ) // Item will be null if its not a 'myObjClass'
{
//Do stuff with item
}
Or with is:
if( objArr[0] is myObjClass )
{
var item = (myObjClass)objArr[0];
//Do stuff with item
}
When using an object array you have to cast to the real type (here: myObjClass) before accessing the fields:
You can access the object like this
((myObjClass)objArr[0]).value
but I would not recommend. CanĀ“t you have your array to be the concrete type
var array = new myObjClass[42]
A compact safe alternative to retrieve the value is
(objArr[0] as myObjClass)?.value
You need to cast object to known type which is myObjClass, like:
((myObjClass)objArr[0]).value.ToString();
Or you can use reflection
var valueString = objArr[0].GetType().GetProperty("value").GetValue(objArr[0]);
Debug.Print(valueString.ToString());
Hope helps,
Technically you can put it as
Debug.Print((objArr[0] as myObjClass)?.value.ToString());
We try casting objArr[0] as myObjClass and if succeed get value and turn it to string. If objArr[0] is not myObjClass we return null as a string
However, a much better way is to implement ToString() in both classes of interest:
public class myObjClass
{
public int value = 5;
public override string ToString() {
// When debugging we want to know "value"
return value.ToString();
}
}
public class myObjClass2
{
public float[] pos = new float[2];
public override string ToString() {
// When debugging we want to know "pos[0]" and "pos[1]" values
return $"{pos[0]} : {pos[1]}";
}
}
And then put an easy
// Just print out debug info (we don't want to know the actual objArr[0] class)
Debug.Print(objArr[0].ToString());
You have a single object, that indeed is an instance of myObjClass, and has a value field, but you have two references to it.
One (myObj) is known to the compiler to be of type myObjClass, and it can guarantee that it has a value field.
The other (objArr[0]) is only known to the compiler to be of type object, and it cannot guarantee that it has a value field.
For example, you could do:
objArr[0] = (random.Next() > 0.5) : myObj ? myObj2
where we're gonna decide at runtime, based on the value of a random number, which will be the type of the actual object at objArr[0].
So, if this was allowed, half of the time objArr[0].value would be correct, and half of the time it will be an error.

Method with Multiple Return Types

I've looked through many questions that are similar to this, but none of them really touched on what I precisely want to do. What I am trying to do is read from an external source a list of variables that also include their data type into a string array:
Example:
ID/Key Type Value/Data;
varName1 bool true;
varName2 string str;
varName3 int 5;
I then store these are objects into a dictionary as objects containing several strings, with the ID also serving as the key.
What I want to do is now create a method that uses a switch statement that casts the string into the correct datatype, and returns it without having to specify anything in the method call. The function should look something like this:
public ??? Method(string key)
{
if(dictionary.ContainsKey(ID))
{
Var temp = dictionary[ID];
switch (temp.Type)
{
case "bool":
return Convert.ToBoolean(temp.Value);
case "int"
return Convert.ToInt(temp.Value);
case "string"
return temp.Value;
}
}
return "NULL";
}
The method call should look something like this:
int x = Method(string key);
string word = Method(string key);
bool isTrue = Method(string key);
Maybe I've missed something, but I have yet to find something that really does something quite like this. Any and all thoughts about this are welcome as well.
In C# 7 you have the option to return multiple values from a method like this:
public (string SomeString, int SomeInt) DoSomething() { ... }
You can get the values like this:
var result = DoSomething();
Console.WriteLine(result.SomeString);
Console.WriteLine(result.SomeInt.ToString());
Or
(var someString, var someInt) = DoSomething();
Console.WriteLine(someString);
Console.WriteLine(someInt.ToString());
This works below the surface with a Tuple and you are not restricted to only 2 values. I don't know how many you can return but I suggest when you need to return that many values, create a class.
More info: https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/
Update
I believe a lot of people are arriving at this question because they're looking for ways to return multiple values generally, not necessarily for the purposes given in the original question. If this is what you want, there are a few options to choose from.
If the combination of your returned types represents a concept that may be useful outside of your method call, consider creating a type to represent that concept. C#'s records provide a nice, concise way to do that:
public record ExtractedValue(bool? BooleanValue, string? StringValue, int? IntValue);
public ExtractedValue Method(string key)
{
...
}
If this is the only place these values will appear together, and it's not really worth coming up with a named type to represent the values, you can also use a Value Tuple. Just be aware that there are some behavioral implications that might bite you if you plan to use the type for things like serialization.
public (bool? BooleanValue, string? StringValue, int? IntValue) Method(string key)
{
...
}
Original Answer
The compiler has no way to distinguish between the three method calls you've provided, because they all look like Method(key);
One option is to return an object and then expect the consuming code to cast it to what they want:
public object Method(string key)
{
if(dictionary.ContainsKey(key))
{
var temp = dictionary[key];
switch (temp.Type)
{
case "bool":
return Convert.ToBoolean(temp.Value);
case "int"
return Convert.ToInt(temp.Value);
case "string"
return temp.Value;
}
}
return "NULL";
}
...
int x = (int) Method(key);
string word = (string) Method(key);
bool isTrue = (bool) Method(key);
You could also use the dynamic keyword to make the cast implicit:
public dynamic Method(string key)
{
if(dictionary.ContainsKey(key))
{
var temp = dictionary[key];
switch (temp.Type)
{
case "bool":
return Convert.ToBoolean(temp.Value);
case "int"
return Convert.ToInt(temp.Value);
case "string"
return temp.Value;
}
}
return "NULL";
}
...
int x = Method(key);
string word = Method(key);
bool isTrue = Method(key);
However, dynamic is a very powerful concept, and it's easy for it to get out of hand, so you have to be really careful with that.
It seems to me that you're expecting your calling code to know which type of object it's expecting to get for each key. It seems like maybe the best approach is to just let the user supply that information:
public T Method<T>(string key)
{
if(dictionary.ContainsKey(key))
return (T) Convert.ChangeType(dictionary[key].Value, typeof(T));
return default(T);
}
...
int x = Method<int>(key);
string word = Method<string>(key);
bool isTrue = Method<bool>(key);
That way, there's no need to track the Type value in your dictionary objects in the first place.
The return type of a function must be typed. As with any other variable or operation, any type that inherits from the specified type is a valid return value (which is why object allows anything as a value).
Personally i dont think it is useful to make one method with multiple return types but if you really want to have one method with multiple return types, you could use the dynamic type in .NET 4.0:
private static void Main(string[] args)
{
int x = Method("varName3");
string word = Method("varName2");
bool isTrue = Method("varName1");
}
private static dynamic Method(string key)
{
var dictionary = new Dictionary<string, KeyValuePair<Type, object>>()
{
{ "varName1", new KeyValuePair<Type, object>(typeof(bool), false) },
{ "varName2", new KeyValuePair<Type, object>(typeof(string), "str") },
{ "varName3", new KeyValuePair<Type, object>(typeof(int), 5) },
};
if (dictionary.ContainsKey(key))
{
return dictionary[key].Value;
}
return null;
}
Hope it helps

In C# can I write a generic function to return null or the value as a string?

Basically I want the following generic function:
public string StringOrNull<T> (T value)
{
if (value != null)
{
return value.ToString();
}
return null;
}
I know I could use a constraint such as where T: class, but T can be a primitive type, Nullable<>, or a class. Is there a generic way to do this?
Edit
Turns out I jumped the gun. This actually works just fine as this sample shows:
class Program
{
static void Main(string[] args)
{
int i = 7;
Nullable<int> n_i = 7;
Nullable<int> n_i_asNull = null;
String foo = "foo";
String bar = null;
Console.WriteLine(StringOrNull(i));
Console.WriteLine(StringOrNull(n_i));
Console.WriteLine(StringOrNull(n_i_asNull));
Console.WriteLine(StringOrNull(foo));
Console.WriteLine(StringOrNull(bar));
}
static private string StringOrNull<T>(T value)
{
if (value != null)
{
return value.ToString();
}
return null;
}
}
default Keyword in Generic Code
In generic classes and methods, one issue that arises is how to assign a default value to a parameterized type T when you do not know the following in advance:
Whether T will be a reference type or a value type.
If T is a value type, whether it will be a numeric value or a struct.
Here's a fun one:
public static class ExtensionFunctions{
public static string ToStringOrNull( this object target ) {
return target != null ? target.ToString() : null;
}
}
The cool part? This will work:
( (string) null ).ToStringOrNull();
So will this:
5.ToStringOrNull();
Extension functions are pretty awesome... they even work on null objects!
If you pass a primitive type, it will automatically be boxed, so you don't need to worry about the null comparison. Since boxing occurs automatically, you can even explicitly compare an int to null without an error, but the result will always be false (and you'll probably get a compiler warning telling you so).
You can use default keyword to return the default of T:
public string StringOrNull<T> (T value)
{
.....
return default(T).ToString();
}
Why generic?
public string StringOrNull (object value)
{
if (value != null){
return value.ToString();
}
return null;
}

Variable generic return type in C#

Is there any way to have a method return any one of a number of generic types from a method? For example, I have the following:
public static T ParseAttributeValue<T>(this XElement element, string attribute)
{
if(typeof(T) == typeof(Int32))
{
return Int32.Parse(element.Attribute(attribute).Value);
}
if(typeof(T) == typeof(Double))
{
return Double.Parse(element.Attribute(attribute).Value);
}
if(typeof(T) == typeof(String))
{
return element.Attribute(attribute).Value;
}
if(typeof(T) == typeof(ItemLookupType))
{
return Enum.Parse(typeof(T), element.Attribute(attribute).Value);
}
}
(This is only a very quick mockup, I'm aware that any production code would need to be significantly more thorough in null checks etc...)
But the compiler doesn't like it, complaining that Int32 cannot be implicitly converted to T (it doesn't work with a cast either). I can understand that. At compile time it has no way to know what T is, but I'm checking it beforehand. Is there anyway I can make this work?
I've done these types of generic methods in the past. The easiest way to get type inference is to provide a generic converter function.
public static T ParseAttributeValue<T>
(this XElement element, string attribute, Func<string, T> converter)
{
string value = element.Attribute(attribute).Value;
if (String.IsNullOrWhiteSpace(value)) {
return default(T);
}
return converter(value);
}
You can use it like the following:
int index = element.ParseAttributeValue("index", Convert.ToInt32);
double price = element.ParseAttributeValue("price", Convert.ToDouble);
You can even provide your own functions and have all the fun in the world (even return anonymous types):
ItemLookupType lookupType = element.ParseAttributeValue("lookupType",
value => Enum.Parse(typeof(ItemLookupType), value));
var item = element.ParseAttributeValue("items",
value => {
List<string> items = new List<string>();
items.AddRange(value.Split(new [] { ',' }));
return items;
});
.Net already has a bunch of great string conversion routines you can use! A TypeConverter can do most of the heavy lifting for you. Then you don't have to worry providing your own parsing implementations for built-in types.
Note that there are locale-aware versions of the APIs on TypeConverter that could be used if you need to handle parsing values expressed in different cultures.
The following code will parse values using the default culture:
using System.ComponentModel;
public static T ParseAttributeValue<T>(this XElement element, string attribute)
{
var converter = TypeDescriptor.GetConverter(typeof(T));
if (converter.CanConvertFrom(typeof(string)))
{
string value = element.Attribute(attribute).Value;
return (T)converter.ConvertFromString(value);
}
return default(T);
}
This will work for a lot of built-in types, and you can decorate custom types with a TypeConverterAttribute to allow them to participate in the type conversion game too. This means that in the future you will be able to parse new types without having to change the implementation of the ParseAttributeValue.
see: http://msdn.microsoft.com/en-us/library/system.componentmodel.typeconverter.aspx
Why are you using the type parameter as the return type at all? This would work, just requires a cast after calling:
public static Object ParseAttributeValue<T>(this XElement element, string attribute)
{
if(typeof(T) == typeof(Int32))
{
return Int32.Parse(element.Attribute(attribute).Value);
}
if(typeof(T) == typeof(Double))
{
return Double.Parse(element.Attribute(attribute).Value);
}
if(typeof(T) == typeof(String))
{
return element.Attribute(attribute).Value;
}
if(typeof(T) == typeof(ItemLookupType))
{
return Enum.Parse(typeof(T), element.Attribute(attribute).Value);
}
}
Or better yet:
public static Int32 ParseAsInt32(this XElement element, string attribute)
{
return Int32.Parse(element.Attribute(attribute).Value);
}
// etc, repeat for each type
This second approach has the additional benefit of having a much higher likelihood of getting inlined, plus it will (for value types like Int32) prevent the need to box/unbox the value. Both of these will cause the method to perform somewhat faster.
Not sure if this is exactly what you want, but you can make the returns work if you cast to object first then to T
public static T ParseAttributeValue<T>(this XElement element, string attribute)
{
if (typeof(T) == typeof(Int32))
{
return (T)(object)Int32.Parse(element.Attribute(attribute).Value);
}
if (typeof(T) == typeof(Double))
{
return (T)(object)Double.Parse(element.Attribute(attribute).Value);
}
if (typeof(T) == typeof(String))
{
return (T)(object)element.Attribute(attribute).Value;
}
return default(T);
}
However you still have to provide T at compile time, calling the method like:
int value = element.ParseAttributeValue<int>("attribute");
Here's two ways of doing it...
static T ReadSetting<T>(string value)
{
object valueObj = null;
if (typeof(T) == typeof(Int32))
valueObj = Int32.Parse(value);
return (T)valueObj;
}
static dynamic ReadSetting2<T>(string value)
{
if (typeof(T) == typeof(Int32))
return Int32.Parse(value);
throw new UnsupportedException("Type is unsupported");
}
static void Main(string[] args)
{
int val1 = ReadSetting<Int32>("2");
int val2 = ReadSetting2<Int32>("3");
}
With C++ templates, this kind of thing would work, but only if each piece of code were in a different, separate specialization. The thing that makes that work is that unused function templates are not compiled (or more accurately: not fully instantiated), so the fact that a piece of code would be invalid if that copy of the template were instantiated with a different type doesn't come up.
C# is different, and AFAIK there's no specialization for generics. One way to accomplish what you are trying to do, while working within the limitations of C# would be to create one function with a more abstract return type, and use the ParseAttributeValue only to cast it to T.
So you would have:
private static Object AbstractParseValue(System.Type t, XElement element, string attribute)
and
public static T ParseAttributeValue<T>(this XElement element, string attribute)
{
return (T)AbstractParseValue(typeof(T), element, attribute);
}
I would suggest that rather than testing the type parameter every time the routine is executed, you should create a generic static class something like this:
internal static class ElementParser<T>
{
public static Func<XElement, string, T> Convert = InitConvert;
T DefaultConvert(XElement element, string attribute)
{
return Default(T); // Or maybe throw exception, or whatever
}
T InitConvert(XElement element, string attribute)
{
if (ElementParser<int>.Convert == ElementParser<int>.InitConvert)
{ // First time here for any type at all
Convert = DefaultConvert; // May overwrite this assignment below
ElementParser<int>.Convert =
(XElement element, string attribute) =>
Int32.Parse(element.Attribute(attribute).Value);
ElementParser<double>.Convert =
(XElement element, string attribute) =>
Int32.Parse(element.Attribute(attribute).Value);
// etc. for other types
}
else // We've done other types, but not this type, and we don't do anything nice for it
{
Convert = DefaultConvert;
}
return Convert(element, attribute);
}
}
public static T ParseAttributeValue(this XElement element, string attribute)
{
ElementParser<T>.Convert(element, attribute);
}
Using this approach, one will only have to do special handling the first time a particular type is used. After that, the conversion can be performed using only a single generic delegate invocation. Once could easily add any number of types, and even allow converters to be registered for any desired type at runtime.

Generic Parse Method without Boxing

I am trying to write a generic Parse method that converts and returns a strongly typed value from a NamedValueCollection. I tried two methods but both of these methods are going through boxing and unboxing to get the value. Does anyone know a way to avoid the boxing? If you saw this in production would you not like it, how bad is it for performance?
Usuage:
var id = Request.QueryString.Parse<int>("id");
Attempt #1:
public static T Parse<T>(this NameValueCollection col, string key)
{
string value = col[key];
if (string.IsNullOrEmpty(value))
return default(T);
if (typeof(T) == typeof(int))
{
//return int.Parse(value); // cannot convert int to T
//return (T)int.Parse(value); // cannot convert int to T
return (T)(object)int.Parse(value); // works but boxes
}
if (typeof(T) == typeof(long))
{
return (T)(object)long.Parse(value); // works but boxes
}
...
return default(T);
}
Attempt #2 (using reflection):
public static T Parse<T>(this NameValueCollection col, string key)
{
string value = col[key];
if (string.IsNullOrEmpty(value))
return default(T);
try
{
var parseMethod = typeof(T).GetMethod("Parse", new Type[] { typeof(string) });
if (parseMethod == null)
return default(T);
// still boxing because invoke returns an object
var parsedVal = parseMethod.Invoke(null, new object[] { value });
return (T)parsedVal;
}
// No Proper Parse Method found
catch(AmbiguousMatchException)
{
}
return default(T);
}
public static T Parse<T>(this NameValueCollection col, string key)
{
return (T)Convert.ChangeType(col[key], typeof(T));
}
I'm not entirely sure of ChangeType boxes or not (I guess reading the docs would tell me, but I'm pressed for time right now), but at least it gets rid of all that type-checking. The boxing overhead is not very high, though, so I wouldn't worry too much about it. If you're worried about run-time type consistency, I'd write the function as:
public static T Parse<T>(this NameValueCollection col, string key)
{
T value;
try
{
value = (T)Convert.ChangeType(col[key], typeof(T));
}
catch
{
value = default(T);
}
return value;
}
This way the function won't bomb if the value cannot be converted for whatever reason. That means, of course, that you'll have to check the returned value (which you'd have to do anyway since the user can edit the querystring).
I think you are over estimating the impact of the boxing/unboxing. The parse method will have a much bigger overhead (string parsing), dwarfing the boxing overhead. Also all the if statements will have a bigger impact. Reflection has the biggest impact of all.
I'd would not like to see this kind of code in production, as there is a cleaner way of doing it. The major problem I have with it is the large number of if statements you will need to cover all cases and the fact that someone could pass any old type to it.
What I would do is write a parse function for each type I want to parse (ie ParseInt()). It's clearer and it is well defined what the function will try to do. Also with short static methods, the compiler is more likely to inline them, saving a function call.
I think this is a bad application of generics, any particular reason for doing it this way?
I'll add a little undocumented way:
public static T Convert<T>()
{
if (typeof(T) == typeof(int))
{
int a = 5;
T value = __refvalue(__makeref(a), T);
return value;
}
else if (typeof(T) == typeof(long))
{
long a = 6;
T value = __refvalue(__makeref(a), T);
return value;
}
throw new NotImplementedException();
}
There is little documentation about them, but they work as of C# 4.0. Read for example here Hidden Features of C#? Remember that undocumented means unsupported, blah blah blah could not work in the future blah blah blah if you use them the devil will come for you blah blah blah :-)
For better readability, you could use a generic dictionary with an anonymous function as follows:
var parserFuncs = new Dictionary<Type, Func<string, object>>() {
{ typeof(int), p => (int) int.Parse(p) },
{ typeof(bool), p => (bool) bool.Parse(p) },
{ typeof(long), p => (long) long.Parse(p) },
{ typeof(short), p => (short) short.Parse(p) },
{ typeof(DateTime), p => (DateTime) DateTime.Parse(p) }
/* ...same for all the other primitive types */
};
return (T) parserFuncs[typeof(T)](value);
Another suggestion for implementation, using a TryParse or Parse method with a generic approach. I wrote this originally to convert strings parsed from a csv file into different types, int, decimal, list, etc.
public static bool TryParse<T>(this string value, out T newValue, T defaultValue = default(T))
where T : struct, IConvertible
{
newValue = defaultValue;
try
{
newValue = (T)Convert.ChangeType(value, typeof(T));
}
catch
{
return false;
}
return true;
}
public static T Parse<T>(this string value)
where T : struct, IConvertible
{
return (T) Convert.ChangeType(value, typeof (T));
}
Here, the try parse method first sets the newValue to the default value, then tries to convert value to type T and return the newValue as type T. If the conversion fails, it returns the default value of T.
The Parse method, simply tries to do the conversion, however if its not fail safe and will throw an exception if the conversion fails.
Am I too late?
static Dictionary<Type, Delegate> table =
new Dictionary<Type, Delegate>{
{ typeof(int), (Func<string,int>)Int32.Parse },
{ typeof(double), (Func<string,double>)Double.Parse },
// ... as many as you want
};
static T Parse<T>(string str)
{
if (!table.TryGet(typeof(T), out Delegate func))
throw new ArgumentException();
var typedFunc = (Func<string, T>)func;
return typedFunc(str);
}
When in trouble with types, try delegates and dicts!
int value = int.Parse(Request.QueryString["RecordID"]);
Here's a suggestion for implementation, following Robert Wagner's logic, but using a generic approach to reduce duplication:
public static int ParseInt32(this NameValueCollection col, string key)
{
return Parse(col, key, int.Parse);
}
public static double ParseDouble(this NameValueCollection col, string key)
{
return Parse(col, key, double.Parse);
}
private static T Parse<T>(NameValueCollection col, string key, Func<string, T> parse)
{
string value = col[key];
if (string.IsNullOrEmpty(value))
return default(T);
return parse(value);
}
Truth be told, returning zero for a null or empty string scares me; this could cause problems if some values are legitimately zero. Instead, I would have the methods return nullables (int?, double?, etc.), which is a slightly more compact approach than the out-parameter pattern used for the framework TryParse methods. You could do this:
public static int? ParseInt32(this NameValueCollection col, string key)
{
return Parse(col, key, int.Parse);
}
public static double? ParseDouble(this NameValueCollection col, string key)
{
return Parse(col, key, double.Parse);
}
private static T? Parse<T>(NameValueCollection col, string key, Func<string, T> parse)
where T : struct
{
string value = col[key];
if (string.IsNullOrEmpty(value))
return default(T?);
return parse(value);
}
But that would still throw an exception for non-null-or-empty strings that aren't numeric. It's better to use TryParse. The built-in Func delegates don't support ref or out parameters, so you'd have to declare your own delegate type, but that is fairly trivial.

Categories

Resources