Alright, I have a generic class. The basics are this:
public class GenericPrimitiveContainer<T> : IGetAndSetGenericValue
{
private T _value;
public T Value
{
get
{
return _value;
}
set
{
_value = value;
}
}
}
Fine enough. I also have a SetValue method in that class which takes an object and sets it to the value which uses this code:
PropertyInfo pi = this.GetType().GetProperty("Value");
pi.SetValue(this, o, null);
That's not all it does because it also checks the type of the object and the type of Value and compares them. If they are the same, o (the object) is assigned to Value. If they're not the same, a conversion is applied. I won't go into that because that's not where the problem is (famous last words I'm sure).
The problem is if Value is of type string. As I said before, I compare the types to see if they are the same. This is as follows ('o' being the object passed in):
Type t1 = Value.GetType();
Type t2 = o.GetType();
if (t1 == t2) ...
If T is int, no problem. If T is String, 'Value' is just 'null'. I can't do 'GetType' on it even to see if it's a String because it's just null.
I have tried, as a test, just getting rid of the checks and testing the set method in a situation where I know a string will be passed to the method. Value was still initially null, but it worked out okay and Value was assigned.
Now I know string is not a primitive and so will work a little differently to an int, but I'm not sure how to overcome this problem. I considered initialising _value to default(T), which didn't work. I also added a constructor to the class which did the same thing. That also didn't work.
I have also tried constraining the class with a 'where t : new()' but that doesn't work because String is not a "non-abstract type with a public parameterless constructor in order to use it as parameter 'T'".
So hopefully someone wiser can help me out on this one.
Your problem is that Value.GetType() doesn't do what you want. Here's a really short complete example:
using System;
static class Generic
{
public static string WhatIsT<T>(T value)
{
return $"T is {value.GetType().FullName}";
}
}
class Program
{
static void Main(string[] args)
{
int i = 5;
Console.WriteLine(Generic.WhatIsT(i));
string s = "hello";
Console.WriteLine(Generic.WhatIsT(s));
s = null;
Console.WriteLine(Generic.WhatIsT(s));
Console.ReadLine();
}
}
The first and second calls to WhatIsT will be fine, but there will be a null reference exception on the third.
If you really really really really need to know the exact name of the generic type you've been closed over - and please heed the caveats in the comments that this almost certainly isn't the right thing to be doing - simply use typeof(T), like this:
return $"T is {typeof(T).FullName}";
Result:
T is System.Int32
T is System.String
T is System.String
Remember, GetType needs an object. typeof just needs a compile time name, which includes type parameters.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With