List.RemoveAll() efficiency / compiler optimisation





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







22















Regarding efficiency, does anyone know if the compiler is clever enough to not create the array containing 1, 3, 5 for each iteration of the loop in the following code?



var foo = new List<int> { 1, 2, 3, 4, 5 };
foo.RemoveAll(i => new { 1, 3, 5 }.Contains(i));


I prefer it for readability, but not at the sake of performance.










share|improve this question




















  • 25





    try for your self sharplab.io

    – Michael Randall
    2 days ago






  • 1





    @MichaelRandall Great site. You should write an answer for this with an short example. This is interesseting for everybody, i think.

    – kara
    2 days ago






  • 1





    I'm really surprised but it looks like it does actually create a new instance of the 3 item array for each iteration inside the method internal bool <M>b__0_0(int i).

    – maxp
    2 days ago




















22















Regarding efficiency, does anyone know if the compiler is clever enough to not create the array containing 1, 3, 5 for each iteration of the loop in the following code?



var foo = new List<int> { 1, 2, 3, 4, 5 };
foo.RemoveAll(i => new { 1, 3, 5 }.Contains(i));


I prefer it for readability, but not at the sake of performance.










share|improve this question




















  • 25





    try for your self sharplab.io

    – Michael Randall
    2 days ago






  • 1





    @MichaelRandall Great site. You should write an answer for this with an short example. This is interesseting for everybody, i think.

    – kara
    2 days ago






  • 1





    I'm really surprised but it looks like it does actually create a new instance of the 3 item array for each iteration inside the method internal bool <M>b__0_0(int i).

    – maxp
    2 days ago
















22












22








22


6






Regarding efficiency, does anyone know if the compiler is clever enough to not create the array containing 1, 3, 5 for each iteration of the loop in the following code?



var foo = new List<int> { 1, 2, 3, 4, 5 };
foo.RemoveAll(i => new { 1, 3, 5 }.Contains(i));


I prefer it for readability, but not at the sake of performance.










share|improve this question
















Regarding efficiency, does anyone know if the compiler is clever enough to not create the array containing 1, 3, 5 for each iteration of the loop in the following code?



var foo = new List<int> { 1, 2, 3, 4, 5 };
foo.RemoveAll(i => new { 1, 3, 5 }.Contains(i));


I prefer it for readability, but not at the sake of performance.







c# arrays list linq compiler-optimization






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 2 days ago









Michael Randall

37.2k84171




37.2k84171










asked 2 days ago









maxpmaxp

9,92735105175




9,92735105175








  • 25





    try for your self sharplab.io

    – Michael Randall
    2 days ago






  • 1





    @MichaelRandall Great site. You should write an answer for this with an short example. This is interesseting for everybody, i think.

    – kara
    2 days ago






  • 1





    I'm really surprised but it looks like it does actually create a new instance of the 3 item array for each iteration inside the method internal bool <M>b__0_0(int i).

    – maxp
    2 days ago
















  • 25





    try for your self sharplab.io

    – Michael Randall
    2 days ago






  • 1





    @MichaelRandall Great site. You should write an answer for this with an short example. This is interesseting for everybody, i think.

    – kara
    2 days ago






  • 1





    I'm really surprised but it looks like it does actually create a new instance of the 3 item array for each iteration inside the method internal bool <M>b__0_0(int i).

    – maxp
    2 days ago










25




25





try for your self sharplab.io

– Michael Randall
2 days ago





try for your self sharplab.io

– Michael Randall
2 days ago




1




1





@MichaelRandall Great site. You should write an answer for this with an short example. This is interesseting for everybody, i think.

– kara
2 days ago





@MichaelRandall Great site. You should write an answer for this with an short example. This is interesseting for everybody, i think.

– kara
2 days ago




1




1





I'm really surprised but it looks like it does actually create a new instance of the 3 item array for each iteration inside the method internal bool <M>b__0_0(int i).

– maxp
2 days ago







I'm really surprised but it looks like it does actually create a new instance of the 3 item array for each iteration inside the method internal bool <M>b__0_0(int i).

– maxp
2 days ago














3 Answers
3






active

oldest

votes


















13














The answer is no it doesn't optimize out the allocation of the array



Basically, every time the predicate is called, it checks against the compiler generated class and initializes a new array to call the Contains (as you can see here)



private sealed class <>c
{
public static readonly <>c <>9 = new <>c();

public static Predicate<int> <>9__0_0;

internal bool <M>b__0_0(int i)
{
// bam!
int obj = new int[3];
RuntimeHelpers.InitializeArray(obj, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
return Enumerable.Contains(obj, i);
}
}





share|improve this answer

































    4














    As @Michael Randall already wrote, it looks like it is not possible.



    I agree, that your questioned code is nicely readable, having the list in the RemoveAll method. But to have the instance only once, I have three ideas of doing it:



    int a = null;
    foo.RemoveAll(i => (a ?? (a = new { 1, 3, 5 })).Contains(i));


    This is actually yours, with little un-beatuness of needing an external variable.



     foo = foo.Except(new { 1, 3, 5 }).ToList();


    That's actually pretty nice solution using Linq.



     new List<int>{1, 3, 5}.ForEach(x => foo.Remove(x));


    new {1, 3, 5}.Iterate(x => foo.Remove(x));


    This is something I'd do. In neary all of my code I have my Extension method "Iterate" to avoid the need of foreach. And also, i dont want to "toList" everything all the time to make a .ForEach(..)



    static class Extensions
    {
    public static void Iterate<TSource>(this IEnumerable<TSource> source, Action<TSource> action)
    {
    foreach (var item in source)
    {
    action.Invoke(item);
    }
    }
    }





    share|improve this answer



















    • 5





      Beware, RemoveAll performs vastly better that multiple calls to Remove.

      – Theodor Zoulias
      2 days ago



















    0














    Since the compiler is not that smart, we must outsmart him.



    var foo = new List<int> { 1, 2, 3, 4, 5 };
    var bar = new HashSet<int>() { 1, 3, 5 };
    foo.RemoveAll(i => bar.Contains(i));





    share|improve this answer



















    • 1





      A hash set of 3 entries will surely not perform better, it would arguably (I have not measured) perform worse.

      – Sefe
      2 days ago






    • 3





      @Sefe While there is probably a difference between the hash set and the array, I think the point of this answer was to create bar outside of the anonymous function so that's it's created only once and to avoid the creation overhead.

      – Joshua Taylor
      2 days ago






    • 2





      @Sefe what you say is true, but I think that the OP provided a trivial example just to illustrate a point. In a real world scenario the lists will be probably longer than that.

      – Theodor Zoulias
      2 days ago














    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55531327%2flistt-removeall-efficiency-compiler-optimisation%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    13














    The answer is no it doesn't optimize out the allocation of the array



    Basically, every time the predicate is called, it checks against the compiler generated class and initializes a new array to call the Contains (as you can see here)



    private sealed class <>c
    {
    public static readonly <>c <>9 = new <>c();

    public static Predicate<int> <>9__0_0;

    internal bool <M>b__0_0(int i)
    {
    // bam!
    int obj = new int[3];
    RuntimeHelpers.InitializeArray(obj, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
    return Enumerable.Contains(obj, i);
    }
    }





    share|improve this answer






























      13














      The answer is no it doesn't optimize out the allocation of the array



      Basically, every time the predicate is called, it checks against the compiler generated class and initializes a new array to call the Contains (as you can see here)



      private sealed class <>c
      {
      public static readonly <>c <>9 = new <>c();

      public static Predicate<int> <>9__0_0;

      internal bool <M>b__0_0(int i)
      {
      // bam!
      int obj = new int[3];
      RuntimeHelpers.InitializeArray(obj, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
      return Enumerable.Contains(obj, i);
      }
      }





      share|improve this answer




























        13












        13








        13







        The answer is no it doesn't optimize out the allocation of the array



        Basically, every time the predicate is called, it checks against the compiler generated class and initializes a new array to call the Contains (as you can see here)



        private sealed class <>c
        {
        public static readonly <>c <>9 = new <>c();

        public static Predicate<int> <>9__0_0;

        internal bool <M>b__0_0(int i)
        {
        // bam!
        int obj = new int[3];
        RuntimeHelpers.InitializeArray(obj, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
        return Enumerable.Contains(obj, i);
        }
        }





        share|improve this answer















        The answer is no it doesn't optimize out the allocation of the array



        Basically, every time the predicate is called, it checks against the compiler generated class and initializes a new array to call the Contains (as you can see here)



        private sealed class <>c
        {
        public static readonly <>c <>9 = new <>c();

        public static Predicate<int> <>9__0_0;

        internal bool <M>b__0_0(int i)
        {
        // bam!
        int obj = new int[3];
        RuntimeHelpers.InitializeArray(obj, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
        return Enumerable.Contains(obj, i);
        }
        }






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 2 days ago









        kara

        2,20031126




        2,20031126










        answered 2 days ago









        Michael RandallMichael Randall

        37.2k84171




        37.2k84171

























            4














            As @Michael Randall already wrote, it looks like it is not possible.



            I agree, that your questioned code is nicely readable, having the list in the RemoveAll method. But to have the instance only once, I have three ideas of doing it:



            int a = null;
            foo.RemoveAll(i => (a ?? (a = new { 1, 3, 5 })).Contains(i));


            This is actually yours, with little un-beatuness of needing an external variable.



             foo = foo.Except(new { 1, 3, 5 }).ToList();


            That's actually pretty nice solution using Linq.



             new List<int>{1, 3, 5}.ForEach(x => foo.Remove(x));


            new {1, 3, 5}.Iterate(x => foo.Remove(x));


            This is something I'd do. In neary all of my code I have my Extension method "Iterate" to avoid the need of foreach. And also, i dont want to "toList" everything all the time to make a .ForEach(..)



            static class Extensions
            {
            public static void Iterate<TSource>(this IEnumerable<TSource> source, Action<TSource> action)
            {
            foreach (var item in source)
            {
            action.Invoke(item);
            }
            }
            }





            share|improve this answer



















            • 5





              Beware, RemoveAll performs vastly better that multiple calls to Remove.

              – Theodor Zoulias
              2 days ago
















            4














            As @Michael Randall already wrote, it looks like it is not possible.



            I agree, that your questioned code is nicely readable, having the list in the RemoveAll method. But to have the instance only once, I have three ideas of doing it:



            int a = null;
            foo.RemoveAll(i => (a ?? (a = new { 1, 3, 5 })).Contains(i));


            This is actually yours, with little un-beatuness of needing an external variable.



             foo = foo.Except(new { 1, 3, 5 }).ToList();


            That's actually pretty nice solution using Linq.



             new List<int>{1, 3, 5}.ForEach(x => foo.Remove(x));


            new {1, 3, 5}.Iterate(x => foo.Remove(x));


            This is something I'd do. In neary all of my code I have my Extension method "Iterate" to avoid the need of foreach. And also, i dont want to "toList" everything all the time to make a .ForEach(..)



            static class Extensions
            {
            public static void Iterate<TSource>(this IEnumerable<TSource> source, Action<TSource> action)
            {
            foreach (var item in source)
            {
            action.Invoke(item);
            }
            }
            }





            share|improve this answer



















            • 5





              Beware, RemoveAll performs vastly better that multiple calls to Remove.

              – Theodor Zoulias
              2 days ago














            4












            4








            4







            As @Michael Randall already wrote, it looks like it is not possible.



            I agree, that your questioned code is nicely readable, having the list in the RemoveAll method. But to have the instance only once, I have three ideas of doing it:



            int a = null;
            foo.RemoveAll(i => (a ?? (a = new { 1, 3, 5 })).Contains(i));


            This is actually yours, with little un-beatuness of needing an external variable.



             foo = foo.Except(new { 1, 3, 5 }).ToList();


            That's actually pretty nice solution using Linq.



             new List<int>{1, 3, 5}.ForEach(x => foo.Remove(x));


            new {1, 3, 5}.Iterate(x => foo.Remove(x));


            This is something I'd do. In neary all of my code I have my Extension method "Iterate" to avoid the need of foreach. And also, i dont want to "toList" everything all the time to make a .ForEach(..)



            static class Extensions
            {
            public static void Iterate<TSource>(this IEnumerable<TSource> source, Action<TSource> action)
            {
            foreach (var item in source)
            {
            action.Invoke(item);
            }
            }
            }





            share|improve this answer













            As @Michael Randall already wrote, it looks like it is not possible.



            I agree, that your questioned code is nicely readable, having the list in the RemoveAll method. But to have the instance only once, I have three ideas of doing it:



            int a = null;
            foo.RemoveAll(i => (a ?? (a = new { 1, 3, 5 })).Contains(i));


            This is actually yours, with little un-beatuness of needing an external variable.



             foo = foo.Except(new { 1, 3, 5 }).ToList();


            That's actually pretty nice solution using Linq.



             new List<int>{1, 3, 5}.ForEach(x => foo.Remove(x));


            new {1, 3, 5}.Iterate(x => foo.Remove(x));


            This is something I'd do. In neary all of my code I have my Extension method "Iterate" to avoid the need of foreach. And also, i dont want to "toList" everything all the time to make a .ForEach(..)



            static class Extensions
            {
            public static void Iterate<TSource>(this IEnumerable<TSource> source, Action<TSource> action)
            {
            foreach (var item in source)
            {
            action.Invoke(item);
            }
            }
            }






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered 2 days ago









            MaliorMalior

            798311




            798311








            • 5





              Beware, RemoveAll performs vastly better that multiple calls to Remove.

              – Theodor Zoulias
              2 days ago














            • 5





              Beware, RemoveAll performs vastly better that multiple calls to Remove.

              – Theodor Zoulias
              2 days ago








            5




            5





            Beware, RemoveAll performs vastly better that multiple calls to Remove.

            – Theodor Zoulias
            2 days ago





            Beware, RemoveAll performs vastly better that multiple calls to Remove.

            – Theodor Zoulias
            2 days ago











            0














            Since the compiler is not that smart, we must outsmart him.



            var foo = new List<int> { 1, 2, 3, 4, 5 };
            var bar = new HashSet<int>() { 1, 3, 5 };
            foo.RemoveAll(i => bar.Contains(i));





            share|improve this answer



















            • 1





              A hash set of 3 entries will surely not perform better, it would arguably (I have not measured) perform worse.

              – Sefe
              2 days ago






            • 3





              @Sefe While there is probably a difference between the hash set and the array, I think the point of this answer was to create bar outside of the anonymous function so that's it's created only once and to avoid the creation overhead.

              – Joshua Taylor
              2 days ago






            • 2





              @Sefe what you say is true, but I think that the OP provided a trivial example just to illustrate a point. In a real world scenario the lists will be probably longer than that.

              – Theodor Zoulias
              2 days ago


















            0














            Since the compiler is not that smart, we must outsmart him.



            var foo = new List<int> { 1, 2, 3, 4, 5 };
            var bar = new HashSet<int>() { 1, 3, 5 };
            foo.RemoveAll(i => bar.Contains(i));





            share|improve this answer



















            • 1





              A hash set of 3 entries will surely not perform better, it would arguably (I have not measured) perform worse.

              – Sefe
              2 days ago






            • 3





              @Sefe While there is probably a difference between the hash set and the array, I think the point of this answer was to create bar outside of the anonymous function so that's it's created only once and to avoid the creation overhead.

              – Joshua Taylor
              2 days ago






            • 2





              @Sefe what you say is true, but I think that the OP provided a trivial example just to illustrate a point. In a real world scenario the lists will be probably longer than that.

              – Theodor Zoulias
              2 days ago
















            0












            0








            0







            Since the compiler is not that smart, we must outsmart him.



            var foo = new List<int> { 1, 2, 3, 4, 5 };
            var bar = new HashSet<int>() { 1, 3, 5 };
            foo.RemoveAll(i => bar.Contains(i));





            share|improve this answer













            Since the compiler is not that smart, we must outsmart him.



            var foo = new List<int> { 1, 2, 3, 4, 5 };
            var bar = new HashSet<int>() { 1, 3, 5 };
            foo.RemoveAll(i => bar.Contains(i));






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered 2 days ago









            Theodor ZouliasTheodor Zoulias

            19719




            19719








            • 1





              A hash set of 3 entries will surely not perform better, it would arguably (I have not measured) perform worse.

              – Sefe
              2 days ago






            • 3





              @Sefe While there is probably a difference between the hash set and the array, I think the point of this answer was to create bar outside of the anonymous function so that's it's created only once and to avoid the creation overhead.

              – Joshua Taylor
              2 days ago






            • 2





              @Sefe what you say is true, but I think that the OP provided a trivial example just to illustrate a point. In a real world scenario the lists will be probably longer than that.

              – Theodor Zoulias
              2 days ago
















            • 1





              A hash set of 3 entries will surely not perform better, it would arguably (I have not measured) perform worse.

              – Sefe
              2 days ago






            • 3





              @Sefe While there is probably a difference between the hash set and the array, I think the point of this answer was to create bar outside of the anonymous function so that's it's created only once and to avoid the creation overhead.

              – Joshua Taylor
              2 days ago






            • 2





              @Sefe what you say is true, but I think that the OP provided a trivial example just to illustrate a point. In a real world scenario the lists will be probably longer than that.

              – Theodor Zoulias
              2 days ago










            1




            1





            A hash set of 3 entries will surely not perform better, it would arguably (I have not measured) perform worse.

            – Sefe
            2 days ago





            A hash set of 3 entries will surely not perform better, it would arguably (I have not measured) perform worse.

            – Sefe
            2 days ago




            3




            3





            @Sefe While there is probably a difference between the hash set and the array, I think the point of this answer was to create bar outside of the anonymous function so that's it's created only once and to avoid the creation overhead.

            – Joshua Taylor
            2 days ago





            @Sefe While there is probably a difference between the hash set and the array, I think the point of this answer was to create bar outside of the anonymous function so that's it's created only once and to avoid the creation overhead.

            – Joshua Taylor
            2 days ago




            2




            2





            @Sefe what you say is true, but I think that the OP provided a trivial example just to illustrate a point. In a real world scenario the lists will be probably longer than that.

            – Theodor Zoulias
            2 days ago







            @Sefe what you say is true, but I think that the OP provided a trivial example just to illustrate a point. In a real world scenario the lists will be probably longer than that.

            – Theodor Zoulias
            2 days ago




















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55531327%2flistt-removeall-efficiency-compiler-optimisation%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            How did Captain America manage to do this?

            迪纳利

            南乌拉尔铁路局