如何在 C# 中使用泛型声明变量

本文关键字:泛型 声明 变量 | 更新日期: 2024-10-24 08:20:54

public static object GetObject(int x)
{
    return new object { };
}
public static object GetObject(string x)
{
    return new object { };
}
public static void ProcessObject<T>(T x) where T : int, string <= got error here: 
{
    object o = GetObject(x);
}

出现错误"用作约束的类型必须是接口、非密封类或类型参数。

如何重写代码以使其工作而无需编写ProcessObject(int x)ProcessObject(string x)两次?

如何在 C# 中使用泛型声明变量

所以你现在拥有的(根据接受的答案和你的评论(是:

public static void ProcessObject<T>(T x)
{
    object o;
    if (typeof(T) == typeof(int))
        o = GetObject((int)(object)x);
    else if (typeof(T) == typeof(string))
        o = GetObject((string)(object)x);
    else
        throw new Exception();
    // do stuff with o
}

我建议公开intstring重载,但为了防止代码重复,请在内部调用另一种方法:

public static void ProcessObject(int x)
{
    ProcessObject(GetObject(x));
}
public static void ProcessObject(string x)
{
    ProcessObject(GetObject(x));
}
private static void ProcessObject(object o)
{
    // do stuff with o
}

这使得public方法的输入值清晰:intstring是唯一可接受的类型,同时仍然不重复实际逻辑(// do stuff with o(。

您可能不喜欢这两种公共ProcessObject方法是彼此重复的(无论如何,表面上;在引擎盖下,它们调用两种不同的GetObject重载(,但我认为这是最好的选择。

你不能做你想做的事情:首先,不可能在一个泛型约束中列出多个类;其次,可以在约束中放置的类型必须能够继承它(如果它是一个接口,则实现它(。intstring都无法通过此检查。在这种情况下,最好使用两个单独的重载。

只需删除where部分

public static void ProcessObject<T>(T x) 
{
    object o = GetObject(x);
}

也不要在其他方法中使用object,而是使用T

C# 中不可能查看类型参数的约束。尝试使用动态

一般来说,如果你的对象根据泛型类型参数做出不同的反应,那么在这种情况下你可能不应该使用泛型。泛型非常适合您希望始终执行相同操作的情况,无论使用什么实际类型。

因此,泛型约束只允许您为类型参数列出一个基类。传递给相应类型参数的任何实际类型都是从指定的基类开始的给定继承层次结构的一部分,因此类的用户可以指定与基类或其任何子类匹配的任何类型。

同时,您(泛型类的作者(可以安全地假定指定类型(至少(具有约束指示的基类的接口。因此,您可以访问基类的任何成员。

如果你想允许stringint,想象一下那可能是什么成员。两者都直接派生自System.Object,因此限制是没有意义的,因为它没有限制;每个类型都派生自 System.Object

总而言之,如果你真的想以不同的方式对待stringint,这绝对是提供两个重载而不是一个泛型类的情况。