【问题标题】:Initialising a generic parameter in a generic class在泛型类中初始化泛型参数
【发布时间】:2019-03-16 12:59:48
【问题描述】:

好的,我有一个通用类。基本情况是这样的:

public class GenericPrimitiveContainer<T> : IGetAndSetGenericValue
{
    private T _value;

    public T Value
    {
        get
        {
            return _value;
        }
        set
        {
            _value = value;
        }
    }
}

足够好。我在该类中还有一个 SetValue 方法,它接受一个对象并将其设置为使用此代码的值:

PropertyInfo pi = this.GetType().GetProperty("Value");
            pi.SetValue(this, o, null);

这还不是全部,因为它还检查对象的类型和 Value 的类型并比较它们。如果它们相同,则将 o(对象)分配给 Value。如果它们不相同,则应用转换。我不会深入讨论,因为这不是问题所在(我敢肯定,著名的遗言)。

问题在于 Value 是否为字符串类型。正如我之前所说,我比较类型以查看它们是否相同。如下('o'为传入的对象):

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

如果 T 是 int,没问题。如果 T 是字符串,则“值”只是“空”。我无法对其执行“GetType”,甚至无法查看它是否为字符串,因为它只是空值。

作为测试,我已经尝试在我知道字符串将传递给方法的情况下摆脱检查并测试 set 方法。 Value 最初仍为 null,但结果正常,并且 Value 已分配。

现在我知道字符串不是原始类型,因此与 int 的工作方式略有不同,但我不确定如何克服这个问题。我考虑将 _value 初始化为 default(T),但没有成功。我还向执行相同操作的类添加了一个构造函数。那也没用。

我也尝试使用 'where t : new()' 来约束类,但这不起作用,因为 String 不是“具有公共无参数构造函数的非抽象类型,以便将其用作参数 'T '"。

所以希望有更聪明的人可以帮助我解决这个问题。

【问题讨论】:

  • null 没有类型,所以你肯定只排除 null 并返回 false,1 != null
  • 我不能不认为这看起来像一个XY problem. 你为什么首先使用反射来设置值?
  • 你能详细说明你为什么在泛型类中做反射魔法吗?创建泛型是为了更方便地使用类型,包括避免反射。

标签: c# generics


【解决方案1】:

你的问题是Value.GetType() 没有做你想做的事。这是一个非常简短的完整示例:

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();
        }
    }

第一次和第二次调用WhatIsT 没问题,但第三次会出现空引用异常。

如果你真的真的真的需要知道你已经关闭的泛型类型的确切名称 - 注意 cmets 中的警告,这几乎肯定是不正确的要做的事情 - 只需使用typeof(T),就像这样:

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

结果:

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

记住,GetType 需要一个对象。 typeof 只需要一个编译时间名称,其中包含类型参数。

【讨论】:

    猜你喜欢
    • 2019-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-22
    • 2016-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多