1

The .Last() method for Lists only returns a value. I would like to be able to do something like this.

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

This is my attempt at writing an extension method (it does not compile)

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

Is what I want to do possible?

edit:

This is an example of where I would want to use it.

 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;

This is why doing

shapes[shapes.Count-1] 

isn't really a solution.

blooop
  • 409
  • 4
  • 15

6 Answers6

7

Just use

a[a.Count-1] = 4;

Or write an extension method

a.SetLast(4);

Even if you could create a faux-extension property, it's not a good idea. This goes double if the solution involves unsafe code.

Thom Smith
  • 13,916
  • 6
  • 45
  • 91
  • Sorry I didn't explain fully the first time, see my edit. I'll look into faux-extension properties. – blooop Jul 26 '12 at 15:56
5

There are no extension properties in C#. But here is an extension method you can use:

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];
    }
}

Here is how to use it

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
    }
}

If you want you can adjust validation behaviour.

Community
  • 1
  • 1
oleksii
  • 35,458
  • 16
  • 93
  • 163
2

You can create an extension method that sets the last element.

For simplicity, this is how it would look without error checking:

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

Of course if you want to do it properly, you would also want error checking:

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;
}
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
1

I'd recommend Thom Smith's solution, but if you'd really like to have property-like access, why not just use a property?

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

Used like:

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

No unsafe code, so it's better. Also, it doesn't preclude the use of LINQ's Last method (the compiler can tell the two apart due to how they're used).

Tim S.
  • 55,448
  • 7
  • 96
  • 122
  • Thanks. Your method does what I want to do syntactically. I asked the question to begin with as I was hoping I wouldn't have to do this, but it looks like this is the easiest way after all. – blooop Jul 26 '12 at 16:18
0
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;
HatSoft
  • 11,077
  • 3
  • 28
  • 43
  • The get is ok but the set will add another value at the bottom of the list instead of swapping it. – Tallmaris Jul 26 '12 at 15:50
  • @Tallmaris i just tested it does not, please can you tell me a bit more – HatSoft Jul 26 '12 at 15:55
  • try doing var foo = new AdvancedList(); foo.Last = 3; this will add 3. Now do foo.Last = 4 and you have two elements in foo, 3 and 4. What OP wants is to swap the last element, so keep the list the same length but just change the last int. – Tallmaris Jul 26 '12 at 16:05
-2

You may say: If you wana set the last value: even more cool would be to pass a new value:

 public static void SetLast(this List<int> ints, int newVal)
    {
         int lastIndex = ints.Count-1;
         ints[lastIndex] = newVal;
    }
Embedd_0913
  • 16,125
  • 37
  • 97
  • 135