简体   繁体   English

初始化泛型类中的泛型参数

[英]Initialising a generic parameter in a generic class

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: 我在该类中也有一个SetValue方法,它接受一个对象并将其设置为使用此代码的值:

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. 这不是它的全部,因为它还检查对象的类型和Value的类型并比较它们。 If they are the same, o (the object) is assigned to Value. 如果它们相同,则将o(对象)分配给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. 问题是如果Value是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): 这如下('o'是传入的对象):

Type t1 = Value.GetType();
        Type t2 = o.GetType();
        if (t1 == t2) ...

If T is int, no problem. 如果T是int,没问题。 If T is String, 'Value' is just 'null'. 如果T是String,'Value'只是'null'。 I can't do 'GetType' on it even to see if it's a String because it's just null. 我甚至不能对它做“GetType”,看它是否是一个String,因为它只是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. 作为测试,我已经尝试过在我知道字符串将传递给方法的情况下摆脱检查并测试set方法。 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. 现在我知道字符串不是原始的,因此对int有一点不同,但我不知道如何克服这个问题。 I considered initialising _value to default(T), which didn't work. 我考虑将_value初始化为默认值(T),但这不起作用。 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'". 我也尝试使用'where t:new()'来约束类,但这不起作用,因为String不是“具有公共无参数构造函数的非抽象类型,以便将其用作参数'T'”。

So hopefully someone wiser can help me out on this one. 所以希望有人能够帮助我解决这个问题。

Your problem is that Value.GetType() doesn't do what you want. 你的问题是Value.GetType()没有你想要的。 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. WhatIsT的第一次和第二次调用WhatIsT ,但第三次调用将会出现空引用异常。

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: 如果你真的真的真的需要知道你已被关闭的泛型类型的确切名称 - 注意评论中的注意事项,这几乎肯定不是正确的做法 - 只需使用typeof(T) ,像这样:

            return $"T is {typeof(T).FullName}";

Result: 结果:

T is System.Int32
T is System.String
T is System.String

Remember, GetType needs an object. 请记住, GetType需要一个对象。 typeof just needs a compile time name, which includes type parameters. typeof只需要一个编译时名称,其中包含类型参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM