列表,不要丢失参考

时间:2010-11-03 11:55:29

标签: c# .net

从采访中回来。我与您分享,欢迎提供一个好的,准确的答案。

目的,你有一个静态方法,这个方法接收你有IList<int> 要取回你可以减去3的值并制作代码。

约束: 原始列表(在主中)有一个堆栈上的引用和堆上的值, 结果必须在与原始列表相同的空间(在堆上)返回(它是一个void方法)。此处显示的解决方案不正确,因为在方法中有一个新指针 在堆栈+堆上创建在方法域中。解决方案?

Bonus:如何更改代码以接收int而不是float,double,....

static void Main(string[] args)
    {
        IList<int> list = new List<int>() { 9, 3, 10, 6, 14, 16, 20};
        CanBeDivedByThree(list);
    }

    static void CanBeDivedByThree(IList<int> list)
    {
        list = (from p in list
                where p % 3 == 0
                orderby p descending
                select p).ToList<int>();
    }

4 个答案:

答案 0 :(得分:8)

这是毫无意义的,因为IList的内部存储不受您的控制。添加(或可能删除)项可能会重新分配内部数据结构。

它特别没有意义,因为样本中的列表包含 value 类型,当您访问它们时,它们仍会被复制。

最后但并非最不重要的是,它基本上是使用托管语言的全部要点,您不必担心内存(al)位置。这些事情是平台的implementation details

接受你的奖金问题:没有简单的方法可以实现这一目标。有人可能会认为使用带有类型约束的泛型可以解决这里的问题(类似static void CanBeDivedByThree<T>(IList<T> list) where T : struct),但问题是C#不支持泛型算法。 C#没有模运算符,可以采用类型为'T'和'int'的泛型参数。

答案 1 :(得分:2)

list.RemoveAll(n => n % 3 == 0);

for (int i = list.Count - 1; i >= 0; --i)
{
    if (list[i] % 3 != 0)
        list.RemoveAt(i);
}

第一种方法仅适用于List<T>

可以使它成为模板方法,但是余数操作对浮点数没有多大意义。

答案 2 :(得分:2)

不幸的是,只有List而不是IList才能实现RemoveAll。所以我首先将它作为扩展方法实现。

public static int RemoveAll<T>(this IList<T> list, Predicate<T> match)
{
  if (match == null)
    throw new ArgumentNullException("match");

  int destIndex=0;
  int srcIndex;
  for(srcIndex=0;srcIndex<list.Count;srcIndex++)
  {
    if(!match(list[srcIndex]))
    {
      //if(srcIndex!=destIndex)//Small optimization, can be left out
        list[destIndex]=list[srcIndex];
      destIndex++;
    }
  }
  for(int removeIndex=list.Count-1;removeIndex>=destIndex;removeIndex--)
  {
    list.RemoveAt(removeIndex);
  }
  return srcIndex-destIndex;
}

然后你可以使用:

list.RemoveAll(n => n % 3 != 0);

然后,您可以将重载用于其他类型。不幸的是,你不能(轻松地)使它成为通用的,因为泛型不适用于运算符重载。

答案 3 :(得分:1)

其他人已经覆盖了列表部分 - 这只是奖励位。

您不能使用C#泛型以静态类型的方式执行此操作,但如果您使用的是C#4,则可以使用动态类型执行此操作。例如:

using System;
using System.Collections.Generic;

class Test
{
    static void Main()
    {
        ShowDivisibleBy3(new List<int> { 1, 3, 6, 7, 9 });
        ShowDivisibleBy3(new List<decimal> { 1.5m, 3.3m, 6.0m, 7m, 9.00m });
    }

    static void ShowDivisibleBy3<T>(IEnumerable<T> source)
    {
        foreach (dynamic item in source)
        {
            if (item % 3 == 0)
            {
                Console.WriteLine(item);
            }
        }
    }
}