返回一个泛型类型而不指定类型参数

3

我需要解释一下关于泛型类类型的问题。

我们以以下愚蠢的方法为例:

    public List<> RandomList()  //Note that the Compiler yells at you for not giving a type parameter
    {
        var RandObj = new Random();
        var myint = RandObj.Next(1,3);

        switch(myint)
        {
            case 1: var StringList = new List<string>{ "Test" };
                return StringList;

            case 2: var IntList = new List<int>{ 1,2,3,4 };
                return IntList;
        }
    }

有没有办法让这个函数起作用?我想知道是否有一种方法可以设置它,以便我可以说:“这个函数返回一个列表。我不确定它将返回什么类型的列表,但它肯定是一个列表。”

List<object> 但这并不理想... - Mitch Wheat
我更关心的是原则。我现在没有具体的实现想法,但这个问题一直困扰着我。 - JHixson
对于第一个参数,它永远不会进入情况2,下一个方法的第二个参数是不包含的,意思是排除的,对于您的情况,您需要执行RandObj.Next(1,3)。哈哈,编辑得好:) - terrybozzio
谢谢。我从来没有真正使用过随机函数,只是为了表达我的想法而将其放在这里,但现在我知道了!=) - JHixson
5个回答

4
要做到这一点,您必须返回一个对于返回对象的所有可能选项都通用的类型,对于两个列表,您可以返回此情况下最佳的选择是 IList
public IList RandomList()
{
    var RandObj = new Random();
    var myint = RandObj.Next(1,3);
    switch(myint)
    {
        case 1: var StringList = new List<string>{ "Test" };
            return StringList;

        case 2: var IntList = new List<int>{ 1,2,3,4 };
            return IntList;
    }
}

其他可能的选择包括objectIEnumerableICollection


太好了,这有助于解释我需要知道的内容。如果将来我创建了一个通用类型,并希望能够像这样做某些事情,我需要确保通用类型实现了一个非通用接口,以便我可以将其用作返回值。 - JHixson

3
原则上,在 C# 语言中,根据规定,您无法这样做。
参见 K.4.2 开放和封闭类型的(相关段落摘录) 在运行时,泛型类型声明中的所有代码都在创建一个由类型参数应用于泛型声明而创建的封闭构造类型的上下文中执行。泛型类型中的每个类型参数都绑定到特定的运行时类型。所有语句和表达式的运行时处理始终发生在封闭类型中,而开放类型仅在编译时处理过程中出现。
编译器需要能够将所有开放类型转换为封闭类型。因此它会抱怨。
如果您想要一致的外部视图,则最好使用接口。这里IList会起到不错的作用。

0
总的来说,我同意SH-的观点,即C#并不是为此而设计的。你可以(不完美地)模拟这个过程。
    public IList<T> RandomList<T>() {
        T targetType = default(T);
        var RandObj = new Random();
        switch(targetType.GetType().Name) {
            case "String": 
                var StringList = new List<string>{ "Test" };
                return (IList<T>) StringList;

            case "Int32": 
                var IntList = new List<int>{ 1,2,3,4 };
                return (IList<T>) IntList;

            default:
                return null;
            }
        }

这意味着你必须在编译时考虑到所有你将与类一起使用的通用类型。你也可以使用“动态”类型来实现这一点。


我有点困惑这段代码的作用。T 什么时候被声明?函数被调用时吗?调用会是什么样子? - JHixson
当你调用函数时,你可以对其进行专门化,例如: var lst = RandomList<String>(); Console.WriteLine(lst.Count); - Dweeberly

0

虽然对于您无法控制的通用类型而言这是不可能的,但只要您掌控对象层次结构,就可以做类似的事情。

请考虑以下定义:

public class Number { };
public class Number<T>: Number {};

public static class NumberGenerator {

   public static Number Generate ( double value ) { return new Number<double>(); }
   public static Number Generate ( int value ) { return new Number<int>(); }

}

虽然有些愚蠢,但它确实满足了您所概述的要求。尽管它只是标准的多态性。


0

不是的。 List<>是一种通用类型定义,但并不是真正意义上的类型,因为它只能用于反射目的。它们应该像C++中一样被称为模板 :P


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接