簡體   English   中英

C#擴展方法而不是迭代

[英]C# Extension method instead of iteration

我想知道,如果有一個擴展方法允許我迭代List並讓我對列表中的每個項目做同樣的事情。 例如:

.RemoveAll(x => x.property == somevalue)

這將刪除滿足條件的每個元素。 但是,如果我有這個:

foreach(object item in lstObjects)
{
    object MyObject = new object();
    MyObject.propertyone = item.property
    MyObject.propertytwo = somevalue;
    anotherlist.Add(MyObject);
}

當然,真正的代碼比這復雜一點。 我的目標是,我找到List<T>.ForEach()而不是foreach使用擴展方法,但我無法使它工作,並且此方法不存在於var列表中。 我也找到了。選擇.Select<> .Where<>在哪里.Where<>但這會返回值,在我的方法中不需要返回任何值。

var convertedItems = lstObjects.Select(item => 
{
    object MyObject = new object();
    MyObject.propertyone = item.property
    MyObject.propertytwo = somevalue;
    return MyObject;
});

anotherList.AddRange(convertedItems);

要么

anotherList = convertedItems.ToList();

如果你想縮短它:

var convertedItems = lstObjects.Select(item => 
    new object {propertyone = item.property, propertytwo = somevalue});

我不確定為什么你想要一個擴展方法。 List<T>.ForEach()將主要執行您喜歡的操作,但您現有的foreach循環既是慣用的又是可讀的。 有沒有理由你不能只寫一個正常的函數來做這個?

public void DoMyThing(IList<object> objects) {
  foreach (var obj in objects) {
    someOtherList.Add(new MyObj() {
      item1 = obj
    });
  }
}

通常,如果您發現需要改變項而不返回值,則不希望使用LINQ或查詢運算符。 只需使用foreach

編輯:建議Select()的答案適用於這個簡單的代碼,但是你說

真正的代碼比這復雜一點

這告訴我你可能不得不在迭代期間改變其他狀態。 Select方法將推遲此突變,直到序列實現為止; 除非您熟悉LINQ查詢如何延遲執行並捕獲外部變量,否則這可能會給您帶來奇怪的結果。

編寫自己的ForEach擴展是微不足道的。 我在所有代碼中都包含以下內容:

    public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action )
    {
        foreach (T item in collection)
        {
            action(item);
        }
    }

您可以通過Select語句完成此操作:

var newList = lstObjects.Select(o => 
                      new { propertyone = o.property, 
                            propertytwo = somevalue }).ToList();

以下是使用lambda表達式的ForEach的方法:

lstObjects.ForEach(item =>
{
    MyObject obj = new MyObject();
    obj.propertyone = item.property;
    obj.propertytwo = somevalue;
    anotherlist.Add(obj);
});

但是你可以看到它看起來與你已經擁有的非常相似!

另外,在我看來, Select可能是您想要做的更好的匹配:

anotherList.AddRange(lstObjects.Select(item => new MyObject()
{
    propertyone = item.property,
    obj.propertytwo = somevalue,
}));
List<MyObjectType> list = new List<MyObjectType>();

list.ForEach((MyObjectType item) => {
    object MyObject = new object() 
    {
        MyObject.propertyone = item.property,
        MyObject.propertytwo = somevalue
    };

    anotherlist.Add(MyObject);
});

如果要在迭代過程中執行操作,可能需要考慮作為Interactive Extensions一部分的.Do方法。 請參見http://www.thinqlinq.com/Post.aspx/Title/Ix-Interactive-Extensions-return

您可以輕松創建擴展方法來執行此操作:

public IEnumerable<T> RemoveAll(this List<T> list, Func<bool, T> condition)
{
   var itemsToRemove = list.Where(s => condition(s));
   list.RemoveAll(itemsToRemove);
}

然后你可以這樣稱呼它:

myList.RemoveAll(x => x.Property == someValue);

編輯:這是另一種做同樣的方法

就“內置”而言,沒有.ForEach() ; 但我覺得.Aggregate()在這里是最合適的選擇(如果你絕對想要一個內置函數)。

lstObjects.Aggregate(anotherList, (targetList, value) =>
    {
        object MyObject = new object();
        MyObject.propertyone = item.property
        MyObject.propertytwo = somevalue;
        targetList.Add(MyObject);
        return targetList;
    });

您顯然可以編寫自己的擴展方法:

public static IEnumerable<T> Intercept<T>(this IEnumerable<T> values, Action<T> each)
{
    foreach (var item in values)
    {
        each(item);
        yield return item;
    }
}

public static IEnumerable<T> Intercept<T>(this IEnumerable<T> values, Action<T, int> each)
{
    var index = 0;
    foreach (var item in values)
    {
        each(item, index++);
        yield return item;
    }
}

// ...
a.Intercept(x => { Console.WriteLine(x); }).Count();

注意:我不像其他人一樣創建ForEach的原因是因為Microsoft沒有包含它,因為通過設計Linq方法總是返回一個值或值列表。

特別是對你的問題, .Select<T>將成功。

anotherList.AddRange(lstObjects.Select(x => new MyObject()
{
  propertyone = x.property,
  propertytwo = somevalue
}));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM