关于arraylist:扩展C#List.Last

Extend C# List.Last

list的.last()方法只返回一个值。我想能做这样的事。

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

这是我试图写一个扩展方法(它不编译)

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

我想做的是可能的吗?

编辑:

这是一个我想在哪里使用它的例子。

1
2
3
 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;

这就是为什么

1
shapes[shapes.Count-1]

不是真正的解决方案。


只使用

1
a[a.Count-1] = 4;

或者写一个扩展方法

1
a.SetLast(4);

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


C中没有扩展属性。但这里有一个扩展方法,您可以使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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];
    }
}

这是如何使用它

1
2
3
4
5
6
7
8
9
10
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
    }
}

如果需要,可以调整验证行为。


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

为了简单起见,这是在不进行错误检查的情况下的外观:

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

当然,如果您想正确地执行此操作,还需要进行错误检查:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
}


我推荐Thom Smith的解决方案,但是如果你真的想拥有像访问这样的属性,为什么不直接使用一个属性呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyList<T> : List<T>
{
    public T Last
    {
        get
        {
            return this[this.Count - 1];
        }
        set
        {
            this[this.Count - 1] = value;
        }
    }
}

用途:

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

没有不安全的代码,所以更好。另外,它也不排除使用linq的Last方法(编译器可以根据它们的使用方式将它们区分开来)。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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;


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

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