-1

I have the following as a way to denormalize a list of integers:

public string DbUsersMessaged { get; set; }

public List<int> UsersMessaged {
    get {
        return string.IsNullOrEmpty(DbUsersMessaged) ? new List<int>() : DbUsersMessaged.Split(',').Select(Int32.Parse).ToList();
    }
    set {
        DbUsersMessaged = value != null ? String.Join(",", value) : null;
    }
}

To read, I can query sersMessaged.Contains(id).

To write, I'd like to simply do UsersMessaged.Add(id), but this doesn't work because set isn't called.

For now, I'm doing this to trigger the set:

UsersMessaged = UsersMessaged.AddReassign(user);
public static List<int> AddReassign(this List<int> list, int item)
{
    var tempList = list;
    if (list.Contains(item))
        return list;
    tempList.Add(item);
    list = tempList;
    return list;
}

But this is not ideal because I have AddReassign throughout. Ideally I can just use Add. Per another answer, I know I can override the Add method via the following:

public class DbList : List<int>
{
  public override void Add(int value)
  {
    // AddReassign logic goes here
  }
}

However I have some questions:

  • How can I move my logic into the overridden Add? I've been struggling with syntax for a while.
  • How would get change in the above? I know I need to return a DbList, but how do I cleanly instantiate a DbList from an IEnumerable?
  • Is there any simple way to make this solution generic, instead of just for int?
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
SB2055
  • 12,272
  • 32
  • 97
  • 202
  • 1
    Write a class that inherits from `List`? – Heretic Monkey Dec 19 '16 at 21:42
  • @MikeMcCaughan that's what I'm struggling with - per the three bullets at the bottom. – SB2055 Dec 19 '16 at 21:45
  • 2
    Use composition, not inheritance. – Servy Dec 19 '16 at 21:46
  • @Servy googling now. If anyone has time to demonstrate their preferred approach, I'd appreciate it. – SB2055 Dec 19 '16 at 21:47
  • 2
    http://stackoverflow.com/questions/21692193/why-not-inherit-from-listt?rq=1 – Servy Dec 19 '16 at 21:48
  • 1
    A couple options: 1) Rather than `List` you could use `ObservableCollection` and listen for additions and removals yourself, OR 2) Rather than maintaining both the list and the string, maintain just the list and recreate the string as required. – dbc Dec 19 '16 at 21:54
  • I guess you could do it a bit like this: https://dotnetfiddle.net/iX5lHL – Icepickle Dec 19 '16 at 22:06
  • @SB2055 Did the .net fiddle help you? – Icepickle Dec 20 '16 at 16:16
  • @Icepickle I tried doing what you've outlined there but I'm getting stuck trying to apply it to my code. I'll try to make a dotnetfiddle to reproduce for you but it probably won't be today. Feel free to make an answer and I can accept it - any help demoing `get` etc would be nice – SB2055 Dec 20 '16 at 23:01

1 Answers1

-1

Inherit and shadow, like this:

class MyList<T> : List<T>
{
    public new void Add(T item)
    {
        if (!this.Contains(item)) base.Add(item);
    }
}

Any methods of the ancestor class that call Add will still call the old version of Add (i.e. there is no polymorphism here), but any of your code that uses the class will call the new version of Add, which will prevent duplicates using the logic you provided.

If you already have a bunch of List<> objects and need to convert them to MyList, add a static "From" method, like this:

class MyList<T> : List<T>
{
    ...
    static public MyList<T> FromList(List<T> source)
    {
        MyList<T> newList = new MyList<T>();
        foreach (var item in source)
        {
            newList.Add(item);
        }
        return newList;
    }
}
John Wu
  • 50,556
  • 8
  • 44
  • 80
  • 2
    That's not overriding the method. That's shadowing it, and the actual `List` method will still be callable. – Servy Dec 19 '16 at 22:22