J'essaie d'utiliser une interface fluide pour créer une collection, similaire à cet exemple (simplifié):

   var a = StartWith(1).Add(2).Add(3).Add(4).ToArray();
   /* a = int[] {1,2,3,4};  */

La meilleure solution que je puisse trouver avec add Add () comme:

  IEnumerable<T> Add<T>(this IEnumerable<T> coll, T item)
  {
     foreach(var t in coll) yield return t;
     yield return item;
  }

Ce qui semble ajouter beaucoup de frais généraux qui vont être répétés à chaque appel.

Y a-t-il un meilleur moyen?

MISE À JOUR: dans ma précipitation, j'ai trop simplifié l'exemple et omis une exigence importante. Le dernier élément de la collection existante influence l'élément suivant. Donc, un exemple un peu moins simplifié:

   var a = StartWith(1).Times10Plus(2).Times10Plus(3).Times10Plus(4).ToArray();
   /* a = int[] {1,12,123,1234};  */

public static IEnumerable<T> StartWith<T>(T x)
{
    yield return x;
}

static public  IEnumerable<int> Times10Plus(this IEnumerable<int> coll, int item)
{
    int last = 0;
    foreach (var t in coll)
    {
        last = t;
        yield return t;
    }
    yield return last * 10 + item;
}
4
James Curran 13 août 2017 à 18:55

2 réponses

Meilleure réponse

Vous pouvez effectuer les opérations suivantes:

public static class MySequenceExtensions
{
    public static IReadOnlyList<int> Times10Plus(
        this IReadOnlyList<int> sequence, 
        int value) => Add(sequence, 
                          value,
                          v => sequence[sequence.Count - 1] * 10 + v);

    public static IReadOnlyList<T> Starts<T>(this T first)
        => new MySequence<T>(first);

    public static IReadOnlyList<T> Add<T>(
        this IReadOnlyList<T> sequence,
        T item,
        Func<T, T> func)
    {
        var mySequence = sequence as MySequence<T> ?? 
                         new MySequence<T>(sequence);
        return mySequence.AddItem(item, func);
    }

    private class MySequence<T>: IReadOnlyList<T>
    {
        private readonly List<T> innerList;

        public MySequence(T item)
        {
            innerList = new List<T>();
            innerList.Add(item);
        }

        public MySequence(IEnumerable<T> items)
        {
            innerList = new List<T>(items);
        }

        public T this[int index] => innerList[index];
        public int Count => innerList.Count;

        public MySequence<T> AddItem(T item, Func<T, T> func)
        {
            Debug.Assert(innerList.Count > 0);
            innerList.Add(func(item));
            return this;
        }

        public IEnumerator<T> GetEnumerator() => innerList.GetEnumerator();
        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
    }
}

Notez que j'utilise IReadOnlyList pour rendre possible l'indexation dans la liste de manière performante et pouvoir obtenir le dernier élément si nécessaire. Si vous avez besoin d'une énumération paresseuse, je pense que vous êtes coincé avec votre idée originale.

Et bien sûr, ce qui suit:

var a = 1.Starts().Times10Plus(2).Times10Plus(3).Times10Plus(4).ToArray();

Produit le résultat attendu ({1, 12, 123, 1234}) avec, ce que je pense être, des performances raisonnables.

1
InBetween 15 août 2017 à 17:46

Vous pouvez faire comme ça:

public interface ISequence
{
    ISequenceOp StartWith(int i);
}

public interface ISequenceOp
{
    ISequenceOp Times10Plus(int i);
    int[] ToArray();
}

public class Sequence : ISequence
{
    public ISequenceOp StartWith(int i)
    {
        return new SequenceOp(i);
    }
}

public class SequenceOp : ISequenceOp
{
    public List<int> Sequence { get; set; }

    public SequenceOp(int startValue)
    {
        Sequence = new List<int> { startValue };
    }

    public ISequenceOp Times10Plus(int i)
    {
        Sequence.Add(Sequence.Last() * 10 + i);
        return this;
    }

    public int[] ToArray()
    {
        return Sequence.ToArray();
    }
}

Et puis juste:

var x = new Sequence();
var a = x.StartWith(1).Times10Plus(2).Times10Plus(3).Times10Plus(4).ToArray();
0
thepirat000 13 juil. 2018 à 17:51