【问题标题】:Extend C# List.Last扩展 C# List.Last
【发布时间】:2012-07-25 06:06:27
【问题描述】:

Lists 的 .Last() 方法只返回一个值。我希望能够做这样的事情。

  List<int> a = new List<int> { 1, 2, 3 };
  a.Last() = 4;

这是我编写扩展方法的尝试(它不会编译)

public unsafe static T* mylast<T>(this List<T> a)
{
   return &a[a.Count - 1];
}

我想做的事可能吗?

编辑:

这是我想要使用它的示例。

 shapes.last.links.last.points.last = cursor;   //what I want the code to look like
 //how I had to write it.
 shapes[shapes.Count - 1].links[shapes[shapes.Count - 1].links.Count - 1].points[shapes[shapes.Count - 1].links[shapes[shapes.Count - 1].links.Count - 1].points.Count-1] = cursor;

这就是为什么这样做

shapes[shapes.Count-1] 

并不是真正的解决方案。

【问题讨论】:

  • 为什么要写这种方法?
  • 看起来他想替换最后一个元素
  • 您是说您想要一种方法将列表中的最后一项设置为右侧指定的值吗?
  • a.Add(4) 还不够吗?或者你想改变最后一个元素?
  • 如果是这样,只需制作一个新版本的Last,它采用T 类型的参数并在方法中设置其自身的值。

标签: c# arraylist extension-methods


【解决方案1】:

你可能会说:如果你想设置最后一个值:更酷的是传递一个新值:

 public static void SetLast(this List<int> ints, int newVal)
    {
         int lastIndex = ints.Count-1;
         ints[lastIndex] = newVal;
    }

【讨论】:

  • OP 正在寻找设置最后一个值。
【解决方案2】:

随便用

a[a.Count-1] = 4;

或者写一个扩展方法

a.SetLast(4);

即使您可以创建虚假扩展属性,这也不是一个好主意。如果解决方案涉及不安全的代码,这会加倍。

【讨论】:

  • 对不起,我第一次没有完全解释清楚,请参阅我的编辑。我将研究人造扩展属性。
【解决方案3】:

您可以创建设置最后一个元素的扩展方法。

为简单起见,这是没有错误检查的外观:

public static class ListExtensions
{
    public static void SetLast<T>(this IList<T> source, T value)
    {
        source[source.Count - 1] = value;
    }
}

当然,如果你想正确地做到这一点,你还需要错误检查:

public static void SetLast<T>(this IList<T> source, T value)
{
    if (source == null)
    {
        throw new ArgumentNullException("source");
    }

    if (source.Count == 0)
    {
        throw new ArgumentException("cannot be empty", "source");
    }

    source[source.Count - 1] = value;
}

【讨论】:

    【解决方案4】:

    C# 中没有extension properties。但这里有一个你可以使用的扩展方法:

    public static class ListEx
    {
        public static void SetLast<T>(this IList<T> list, T value)
        {
            if (list == null)
                throw new ArgumentNullException("list");
            if(list.Count == 0)
                throw new ArgumentException(
                    "Cannot set last item because the list is empty");
    
            int lastIdx = list.Count - 1;
            list[lastIdx] = value;
        }
    
        //and by symmetry
        public static T GetLast<T>(this IList<T> list)
        {
            if (list == null)
                throw new ArgumentNullException("list");
            if (list.Count == 0)
                throw new ArgumentException(
                    "Cannot get last item because the list is empty");
    
            int lastIdx = list.Count - 1;
            return list[lastIdx];
        }
    }
    

    这里是如何使用它

    class Program
    {
        static void Main(string[] args)
        {
            List<int> a = new List<int> { 1, 2, 3 };
            a.SetLast(4);
            int last = a.GetLast(); //int last is now 4
            Console.WriteLine(a[2]); //prints 4
        }
    }
    

    如果您愿意,您可以调整验证行为。

    【讨论】:

      【解决方案5】:
      public class AdvancedList : List<int>
      {
          public int Last
          {
              get { return this[Count - 1]; }
              set
              {
                  if(Count >= 1 )
                      this[Count - 1] = value;
                  else
                      Add(value);
              }
          }
      }
      
      AdvancedList advancedList = new AdvancedList();
      advancedList.Add(100);
      advancedList.Add(200);
      
      advancedList.Last = 10;
      
      advancedList.Last = 11;
      

      【讨论】:

      • get 没问题,但是 set 会在列表底部添加另一个值,而不是交换它。
      • @Tallmaris 我刚刚测试过它没有,请你再告诉我一点
      • 尝试做 var foo = new AdvancedList(); foo.Last = 3;这将添加 3。现在执行 foo.Last = 4 并且您在 foo 中有两个元素,3 和 4。OP 想要交换最后一个元素,所以保持列表相同的长度,但只需更改最后一个 int。跨度>
      【解决方案6】:

      我推荐 Thom Smith 的解决方案,但如果您真的想拥有类似属性的访问权限,为什么不直接使用属性呢?

      public class MyList<T> : List<T>
      {
          public T Last
          {
              get
              {
                  return this[this.Count - 1];
              }
              set
              {
                  this[this.Count - 1] = value;
              }
          }
      }
      

      像这样使用:

      var m = new MyList<int> { 1, 2, 3 };
      m.Last = 4;
      Console.WriteLine(m.Last);
      

      没有不安全的代码,所以更好。此外,它不排除使用 LINQ 的 Last 方法(编译器可以根据它们的使用方式区分这两者)。

      【讨论】:

      • 谢谢。你的方法在语法上做了我想做的事情。我一开始就问了这个问题,因为我希望我不必这样做,但看起来这毕竟是最简单的方法。
      猜你喜欢
      • 2019-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-09
      • 2010-12-05
      相关资源
      最近更新 更多