【问题标题】:How to instantiate a generic list without knowing the type如何在不知道类型的情况下实例化通用列表
【发布时间】:2011-09-27 23:18:40
【问题描述】:

我创建了一个方法来组织一个不知道类型的通用列表,如果它的 int 或 decimal 它将排序。

但是,从文本框中检索值的代码使用 List

我尝试将其转换为 List,但它不起作用。 如果他们在文本框中键入整数、小数或字符串,我希望此代码能够正常工作。

这是面试问题的一部分,他们要求不要使用排序方法,并且输入应该接收例如 INTS 或 DECIMALS

private void btnSort_Click(object sender, EventArgs e)
        {
            List<int> list = new List<int>();
            list.Add(int.Parse(i1.Text));
            list.Add(int.Parse(i2.Text));
            list.Add(int.Parse(i3.Text));
            list.Add(int.Parse(i4.Text));
            list.Add(int.Parse(i5.Text));
            Sort(list);
            StringBuilder sb = new StringBuilder();
            foreach (int t in list)
            {
                sb.Append(t.ToString());
                sb.AppendLine();
            }
            result.Text = sb.ToString();
        }


        private void Sort<T>(List<T> list)
        {
            bool madeChanges;
            int itemCount = list.Count;
            do
            {
                madeChanges = false;
                itemCount--;
                for (int i = 0; i < itemCount; i++)
                {
                    int result = Comparer<T>.Default.Compare(list[i], list[i + 1]);

                    if (result > 0)
                    {
                        Swap(list, i, i + 1);
                        madeChanges = true;
                    }
                }
            } while (madeChanges);
        }


        public List<T> Swap<T>(List<T> list,
                int firstIndex,
                int secondIndex)
        {
            T temp = list[firstIndex];
            list[firstIndex] = list[secondIndex];
            list[secondIndex] = temp;

            return list;
        }

我想要这样的东西:但给出错误 错误 1 ​​找不到类型或命名空间名称“T”(是否缺少 using 指令或程序集引用?) c:\users\luis.simbios\documents\visual studio 2010\Projects\InterViewPreparation1\InterViewPreparation1\Generics\ GenericsSorting1.cs 22 18 InterViewPreparation1

列表列表 = 新列表(); list.Add(i1.Text); list.Add(i2.Text); 排序(列表);

【问题讨论】:

  • 为什么,请告诉我,你不使用List&lt;T&gt;.Sort吗?
  • +1 给杰森。这是文档:msdn.microsoft.com/en-us/library/b0zbh7b6.aspx
  • 因为这是一个面试问题,他们要求不要使用排序方法。
  • 如何更改第一行,使其不使用 List,如果我尝试执行 List,则会出现编译器错误。

标签: c# .net generics


【解决方案1】:

因为这是一个面试问题,他们要求不要使用 排序方法。

在这种情况下,您可以添加通用约束IComparable&lt;T&gt;,然后使用CompareTo() 方法:

 private void Sort<T>(List<T> list) where T : IComparable<T>
 {
    //...
 }

编辑:

您必须编写自定义代码来确定输入是字符串、整数还是十进制,即使用TryParse(..) - 不过这将非常脆弱。一旦你知道类型(一种或另一种方式),你可以使用MakeGenericType()Activator.CreateInstance() 在运行时创建你的List&lt;T&gt; 对象,然后使用MakeGenericMethod() 调用你的泛型方法:

Type type = typeof(string);
IList list = (IList) Activator.CreateInstance(typeof(List<>).MakeGenericType(type));
//add items to list here

var p = new Program();
MethodInfo method = typeof(Program).GetMethod("Sort");
MethodInfo genericMethod = method.MakeGenericMethod(new Type[] { type });
genericMethod.Invoke(p, new [] {list} );

我很确定这不是面试问题打算要求的。

【讨论】:

  • 我明白,但我的问题是如何实例化列表,所以我不必定义列表的内容是整数还是小数。这甚至可能吗?列表 列表 = 新列表(); list.Add(i1.Text);
  • @Luis:你想检测输入类型是什么?您必须至少在运行时知道类型是什么才能在此处使用泛型
  • 是的,这是我的想法,我不知道这是不可能的。但至少我做的排序方法是通用的。
  • @Luis:更新了答案 - 我很确定这不是面试官的目的。
【解决方案2】:

首先,正如 Jason 指出的那样,让平台为您完成工作 - 调用 .Sort。

其次,在我看来,您将不得不根据检查文本框的内容来选择列表的“T”,以便您可以处理整数与字符串等。然后将项目分配给基于此的列表。但是一旦你决定了,你的排序就不会在乎了。

【讨论】:

  • 请检查编辑。这是一个面试问题,他们说不要使用排序方法,并且输入可以是整数或小数。
  • @Luis:同时?抱歉,您的问题非常不清楚。
  • 不,我的想法是在 5 个文本框中,一个用户可以输入 5 个整数,但另一个用户可以输入 5 个小数
【解决方案3】:

你没有以正确的方式解决这个问题。正确地拥抱泛型。你想要的是这样的:

public string Foo<T>(IEnumerable<string> strings) where T : struct, IComparable<T> {
    var list = strings.Select(s => (T)Convert.ChangeType(s, typeof(T))).ToList();
    list.Sort((x, y) => (x.CompareTo(y)));
    return String.Join("\n", list);
}

现在你可以说

string response = Foo<int>(strings);

string response = Foo<decimal>(strings);

取决于你想要的。

注意

  1. 我们使用List&lt;T&gt;.Sort 进行排序。
  2. 我们使用String.Join 构建字符串以显示给用户。

这应该可以编译,但如果没有,请原谅一些琐碎的错误。我现在无法启动 ol' 编译器。

编辑:我看到你编辑了你不能使用List&lt;T&gt;.Sort。用您自己的实现替换我对List&lt;T&gt;.Sort 的使用很容易。

【讨论】:

  • 我明白,但我的问题更多是关于如何实例化一个您不知道文本框中的用户是要输入整数还是小数的列表。
  • @Luis:你什么意思?用户可以同时输入intdecimal吗?
  • 不,我的想法是在 5 个文本框中,一个用户可以输入 5 个整数,但另一个用户可以输入 5 个小数。
  • 好吧,我就是这么想的。我为你解决了这个问题,你看到了吗?如果用户在int 文本框中输入,那么您将该输入放入一个字符串序列中(称为strings)并调用Foo&lt;int&gt;(strings)。如果用户在decimal 文本框中输入,那么您将该输入放入一个字符串序列中(称为strings)并调用Foo&lt;decimal&gt;(string)
【解决方案4】:

尝试类似:

private static IList foobar(Type t) 
{ 
  var listType = typeof(List<>); 
  var constructedListType = listType.MakeGenericType(t); 
  var instance = Activator.CreateInstance(constructedListType); 
  return (IList)instance; 
}

然后使用:

IList list = foobar(TYPE); 

TYPE 是您希望列出的类型。

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-21
    • 1970-01-01
    • 2018-01-11
    • 2013-02-24
    相关资源
    最近更新 更多