Re: random sorting a collection

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jon Skeet [C# MVP]

    #1

    Re: random sorting a collection

    Peter Duniho <NpOeStPeAdM@nn owslpianmk.comw rote:
    As a side-note: I was intrigued to find that when the target of the
    "orderby" clause is more complex -- for example, a lamba expression taking
    a parameter and returning a value -- the compiler doesn't like that,
    complaining that it can't do type inference. In spite of the fact that
    simply replacing "orderby" with an explicit call to the "OrderBy()" method
    fixes it.
    Could you give an example of what you mean? I'll try to work out what's
    going on and whether there's a way round it.
    And I
    don't what happens if the rnd.Next call returns a duplicate number in
    the range and how that affects the ordering of the results.
    >
    I don't recall if the sort used in .NET is stable.
    Enumerable.Orde rBy is stable. List.Sort isn't.

    --
    Jon Skeet - <skeet@pobox.co m>
    Web site: http://www.pobox.com/~skeet
    Blog: http://www.msmvps.com/jon.skeet
    C# in Depth: http://csharpindepth.com
  • Peter Duniho

    #2
    Re: random sorting a collection

    On Thu, 29 May 2008 11:41:21 -0700, Jon Skeet [C# MVP] <skeet@pobox.co m>
    wrote:
    Peter Duniho <NpOeStPeAdM@nn owslpianmk.comw rote:
    >As a side-note: I was intrigued to find that when the target of the
    >"orderby" clause is more complex -- for example, a lamba expression
    >taking
    >a parameter and returning a value -- the compiler doesn't like that,
    >complaining that it can't do type inference. In spite of the fact that
    >simply replacing "orderby" with an explicit call to the "OrderBy()"
    >method
    >fixes it.
    >
    Could you give an example of what you mean? I'll try to work out what's
    going on and whether there's a way round it.
    The original example was:

    orderby rnd.Next(intege rs.Count)

    I tried this:

    orderby () ={ Console.WriteLi ne("orderby called"); return
    rnd.Next(intege rs.Count); }

    And this:

    orderby iElement ={ Console.WriteLi ne("orderby for element "
    + iElement); return rnd.Next(intege rs.Count); }

    And this:

    orderby (int iElement) ={ Console.WriteLi ne("orderby for element "
    + iElement); return rnd.Next(intege rs.Count); }

    And this:

    orderby delegate(int iElement) { Console.WriteLi ne("orderby for
    element " + iElement); return rnd.Next(intege rs.Count); }

    But none of those worked. This did, though:

    .OrderBy(iEleme nt ={ Console.WriteLi ne("orderby for element "
    + iElement); return rnd.Next(intege rs.Count); })

    I suspect that most, if not all, of the other examples would have worked
    with the OrderBy() method too, given how semantically close or identical
    they are to the syntax that did work. I just didn't get that far, because
    the first try worked fine. :)

    Even just an explanation as to what's going on would be most helpful.

    Thanks!
    Pete

    Comment

    • Peter Duniho

      #3
      Re: random sorting a collection

      On Thu, 29 May 2008 13:53:07 -0700, Jon Skeet [C# MVP] <skeet@pobox.co m>
      wrote:
      [...]
      >I know, that's not really the right thing to say either. As you say,
      >not
      >only is it an expression, it _must_ be an expression that can be
      >evaluated.
      >
      What kind of expression can't be evaluated? Or do you mean in terms of
      the context (your next sentence).
      The latter. And just to complicate things, part of the issue is the
      dual-purpose of lambda expressions as both a delegate type and an
      expression tree type. No doubt this is part of the power of lambda
      expressions, but it also complicates them.

      Thanks again!

      Pete

      Comment

      • Jon Skeet [C# MVP]

        #4
        Re: random sorting a collection

        Peter Duniho <NpOeStPeAdM@nn owslpianmk.comw rote:
        What kind of expression can't be evaluated? Or do you mean in terms of
        the context (your next sentence).
        >
        The latter. And just to complicate things, part of the issue is the
        dual-purpose of lambda expressions as both a delegate type and an
        expression tree type. No doubt this is part of the power of lambda
        expressions, but it also complicates them.
        It complicates things a bit, but even without them you'd still need the
        cast.

        Consider C# 2 - you couldn't write:

        Delegate d = delegate(int x) { Console.WriteLi ne(x); }

        The compiler needs to know which concrete delegate type to create an
        instance of. Arguably it could try the various Action and Func
        delegates if nothing more specified were provided, I suppose...

        --
        Jon Skeet - <skeet@pobox.co m>
        Web site: http://www.pobox.com/~skeet
        Blog: http://www.msmvps.com/jon.skeet
        C# in Depth: http://csharpindepth.com

        Comment

        • Peter Duniho

          #5
          Re: random sorting a collection

          On Thu, 29 May 2008 14:56:08 -0700, Jon Skeet [C# MVP] <skeet@pobox.co m>
          wrote:
          It complicates things a bit, but even without them you'd still need the
          cast.
          >
          Consider C# 2 - you couldn't write:
          >
          Delegate d = delegate(int x) { Console.WriteLi ne(x); }
          >
          The compiler needs to know which concrete delegate type to create an
          instance of. Arguably it could try the various Action and Func
          delegates if nothing more specified were provided, I suppose...
          I understand the example you give, but not how it relates.

          While the compiler is complaining about not being able to perform
          inference on the type, it's my opinion that the expression "(int iElement)
          =return rnd.Next(intege rs.Count);" needs no additional information.
          This is borne out by the fact that using that directly in the OrderBy()
          method works fine. (Note: I realize this isn't actually true...it's just
          how I think it _ought_ to be...see below).

          It seems to me that the real issue here is how the expansion works, in
          that it's a straight "search and replace" sort of expansion in which a
          lambda expression is simply not an appropriate input.

          I (think) I get why the compiler says what it says. Different parts of
          the compiler are probably responsible for different parts of the process;
          there's effectively a pre-processor doing the "search and replace" part,
          and by the time that then is tried to be compiled into IL, it's not only
          just plain wrong, there's no enough type information for any inference to
          be done. Hence the actual error message.

          So, sure...the cast is required...but the real gimmick in the code you
          posted is the final "()" that actually _calls_ the delegate. That changes
          the lambda expression, after casting, into something that can then be
          inserted into yet another lambda expression for actual evaluation. Even
          with a cast, a lambda expression by itself wouldn't work.

          Finally, I do admit to remaining a little confused about the lack of type
          inference for un-cast delegates (this is the "see below" I mentioned :)
          ). In particular, I'm not really sure why the language won't create some
          sort of implicit delegate type for the purposes of doing type inference.
          A common statement is one that looks like:

          myControl.Invok e((MethodInvoke r) delegate { // some code });

          The cast is required because of the reason you state. But Invoke()
          actually just takes a Delegate. Why can't the compiler generate an
          anonymous type (sort of like it does with "var") that can then be used?
          It's not like the compiler doesn't know the method signature, is it? I
          mean, I _think_ it should know the signature...if there's some reason it
          doesn't, it's not obvious to me.

          Pete

          Comment

          • Jon Skeet [C# MVP]

            #6
            Re: random sorting a collection

            On May 30, 1:31 am, "Peter Duniho" <NpOeStPe...@nn owslpianmk.com>
            wrote:

            <snip>
            I understand the example you give, but not how it relates.
            I'll attempt to make things clearer :)
            While the compiler is complaining about not being able to perform
            inference on the type, it's my opinion that the expression "(int iElement)
            =return rnd.Next(intege rs.Count);" needs no additional information.
            It does. That expression in itself doesn't have a known type. It can
            be converted to a delegate type in itself.
            This is borne out by the fact that using that directly in the OrderBy()
            method works fine. (Note: I realize this isn't actually true...it's just
            how I think it _ought_ to be...see below).
            The reason it works for OrderBy is that OrderBy's parameter is a
            Func<TSource,TK ey(or something similar - I've lost my network
            connection at the minute). It can convert

            (iElement) ="foo"

            into a Func<int, stringvery easily. However, when you put in an
            extra level of lambda expressions, it won't manage it - if you call

            OrderBy(first =(second ="foo"))

            you'll get the same type inference problem - it can't infer the TKey
            type.

            (It's possible you understood all of this bit already - just thought
            I'd restate it for clarity.)
            It seems to me that the real issue here is how the expansion works, in
            that it's a straight "search and replace" sort of expansion in which a
            lambda expression is simply not an appropriate input.
            It's not an appropriate input when the compiler needs to do type
            inference. If you wrote a type with the appropriate LINQ operators
            where OrderBy was declared to accept a
            Func<TSource,Fu nc<TSource,TKey >instead, I think it would cope just
            fine.
            I (think) I get why the compiler says what it says. Different parts of
            the compiler are probably responsible for different parts of the process;
            there's effectively a pre-processor doing the "search and replace" part,
            and by the time that then is tried to be compiled into IL, it's not only
            just plain wrong, there's no enough type information for any inference to
            be done. Hence the actual error message.
            Sort of. The query expression expansion part is indeed relatively
            plain. But I don't think that's the root cause - the root cause is the
            inability to infer a whole type directly from a lambda expression (as
            opposed to inferring some of the parameter types or the return type,
            based on knowledge of the general shape of what it's meant to be
            converted to).
            So, sure...the cast is required...but the real gimmick in the code you
            posted is the final "()" that actually _calls_ the delegate. That changes
            the lambda expression, after casting, into something that can then be
            inserted into yet another lambda expression for actual evaluation. Even
            with a cast, a lambda expression by itself wouldn't work.
            It wouldn't actually *work*, but I think it would compile.
            Finally, I do admit to remaining a little confused about the lack of type
            inference for un-cast delegates (this is the "see below" I mentioned :)
            ). In particular, I'm not really sure why the language won't create some
            sort of implicit delegate type for the purposes of doing type inference.
            A common statement is one that looks like:
            >
            myControl.Invok e((MethodInvoke r) delegate { // some code });
            >
            The cast is required because of the reason you state. But Invoke()
            actually just takes a Delegate. Why can't the compiler generate an
            anonymous type (sort of like it does with "var") that can then be used?
            Just to be clear for any other readers - it's not "var" that creates
            anonymous types, it's expressions of the form new { Property =
            Value }. "var" is just how you cope with the fact that you can't tell
            the compiler what the type's name is. You can in fact use anonymous
            types without var, and var without anonymous types.

            However, yes, it would be possible for the compiler to create a new
            delegate type for you - or try to use one of the existing generic
            ones, as mentioned before. Personally I don't think the extra
            complexity in the language (particularly with respect to overloading -
            there are a few nasty cases I can think of off-hand) but I would
            imagine it would be doable.
            It's not like the compiler doesn't know the method signature, is it? I
            mean, I _think_ it should know the signature...if there's some reason it
            doesn't, it's not obvious to me.
            In the MethodInvoker example you gave it knows one potential
            signature. It doesn't know what parameters it could use, because
            you've used the syntax which says "I don't care about parameters."
            With the more explicit syntax (e.g. delegate() { ... }) it would have
            more information.

            Jon

            Comment

            • Jon Skeet [C# MVP]

              #7
              Re: random sorting a collection

              On May 30, 1:31 am, "Peter Duniho" <NpOeStPe...@nn owslpianmk.com>
              wrote:

              <snip>
              I understand the example you give, but not how it relates.
              I'll attempt to make things clearer :)
              While the compiler is complaining about not being able to perform
              inference on the type, it's my opinion that the expression "(int iElement)
              =return rnd.Next(intege rs.Count);" needs no additional information.
              It does. That expression in itself doesn't have a known type. It can
              be converted to a delegate type in itself.
              This is borne out by the fact that using that directly in the OrderBy()
              method works fine. (Note: I realize this isn't actually true...it's just
              how I think it _ought_ to be...see below).
              The reason it works for OrderBy is that OrderBy's parameter is a
              Func<TSource,TK ey(or something similar - I've lost my network
              connection at the minute). It can convert

              (iElement) ="foo"

              into a Func<int, stringvery easily. However, when you put in an
              extra level of lambda expressions, it won't manage it - if you call

              OrderBy(first =(second ="foo"))

              you'll get the same type inference problem - it can't infer the TKey
              type.

              (It's possible you understood all of this bit already - just thought
              I'd restate it for clarity.)
              It seems to me that the real issue here is how the expansion works, in
              that it's a straight "search and replace" sort of expansion in which a
              lambda expression is simply not an appropriate input.
              It's not an appropriate input when the compiler needs to do type
              inference. If you wrote a type with the appropriate LINQ operators
              where OrderBy was declared to accept a
              Func<TSource,Fu nc<TSource,TKey >instead, I think it would cope just
              fine.
              I (think) I get why the compiler says what it says. Different parts of
              the compiler are probably responsible for different parts of the process;
              there's effectively a pre-processor doing the "search and replace" part,
              and by the time that then is tried to be compiled into IL, it's not only
              just plain wrong, there's no enough type information for any inference to
              be done. Hence the actual error message.
              Sort of. The query expression expansion part is indeed relatively
              plain. But I don't think that's the root cause - the root cause is the
              inability to infer a whole type directly from a lambda expression (as
              opposed to inferring some of the parameter types or the return type,
              based on knowledge of the general shape of what it's meant to be
              converted to).
              So, sure...the cast is required...but the real gimmick in the code you
              posted is the final "()" that actually _calls_ the delegate. That changes
              the lambda expression, after casting, into something that can then be
              inserted into yet another lambda expression for actual evaluation. Even
              with a cast, a lambda expression by itself wouldn't work.
              It wouldn't actually *work*, but I think it would compile.
              Finally, I do admit to remaining a little confused about the lack of type
              inference for un-cast delegates (this is the "see below" I mentioned :)
              ). In particular, I'm not really sure why the language won't create some
              sort of implicit delegate type for the purposes of doing type inference.
              A common statement is one that looks like:
              >
              myControl.Invok e((MethodInvoke r) delegate { // some code });
              >
              The cast is required because of the reason you state. But Invoke()
              actually just takes a Delegate. Why can't the compiler generate an
              anonymous type (sort of like it does with "var") that can then be used?
              Just to be clear for any other readers - it's not "var" that creates
              anonymous types, it's expressions of the form new { Property =
              Value }. "var" is just how you cope with the fact that you can't tell
              the compiler what the type's name is. You can in fact use anonymous
              types without var, and var without anonymous types.

              However, yes, it would be possible for the compiler to create a new
              delegate type for you - or try to use one of the existing generic
              ones, as mentioned before. Personally I don't think the extra
              complexity in the language (particularly with respect to overloading -
              there are a few nasty cases I can think of off-hand) but I would
              imagine it would be doable.
              It's not like the compiler doesn't know the method signature, is it? I
              mean, I _think_ it should know the signature...if there's some reason it
              doesn't, it's not obvious to me.
              In the MethodInvoker example you gave it knows one potential
              signature. It doesn't know what parameters it could use, because
              you've used the syntax which says "I don't care about parameters."
              With the more explicit syntax (e.g. delegate() { ... }) it would have
              more information.

              Jon

              Comment

              • Peter Duniho

                #8
                Re: random sorting a collection

                On Thu, 29 May 2008 23:23:39 -0700, Jon Skeet [C# MVP] <skeet@pobox.co m>
                wrote:
                [...]
                >While the compiler is complaining about not being able to perform
                >inference on the type, it's my opinion that the expression "(int
                >iElement)
                >=return rnd.Next(intege rs.Count);" needs no additional information.
                >
                It does. That expression in itself doesn't have a known type. It can
                be converted to a delegate type in itself.
                Well, I understand the language doesn't support it. But it's what I was
                talking about toward the end of my previous post. The expression has
                enough information that it _could_ be converted into a type (that the
                compiler makes up).
                >This is borne out by the fact that using that directly in the OrderBy()
                >method works fine. (Note: I realize this isn't actually true...it's
                >just
                >how I think it _ought_ to be...see below).
                >
                The reason it works for OrderBy is that OrderBy's parameter is a
                Func<TSource,TK ey>
                I think the way I wrote my paragraph might have miscommunicated my point..
                I understand in the context of OrderBy() that things work. The "this
                isn't actually true" that I was referring to was the question of whether
                the compiler can just make up a type for the purpose of inference.

                Having successfully used OrderBy() to allow the inference to work (see my
                previous post where that was the one way I got things to work :) ), I am
                definitely aware that _that_ approach does work. :)
                [...] However, when you put in an
                extra level of lambda expressions, it won't manage it - if you call
                >
                OrderBy(first =(second ="foo"))
                >
                you'll get the same type inference problem - it can't infer the TKey
                type.
                Right. That was my point when I that it's not really a type inference
                problem per se, but rather than the "search and replace" nature of the
                "orderby" statement creates a type inference problem. While the lambda
                expression I wrote itself contains enough information for _it_ to be
                converted to a type by inference, once it's wrapped in yet another lambda
                expression, that information isn't available/relevant to the compiler.
                (It's possible you understood all of this bit already - just thought
                I'd restate it for clarity.)
                >
                >It seems to me that the real issue here is how the expansion works, in
                >that it's a straight "search and replace" sort of expansion in which a
                >lambda expression is simply not an appropriate input.
                >
                It's not an appropriate input when the compiler needs to do type
                inference.
                I thought that's what I wrote. :)
                If you wrote a type with the appropriate LINQ operators
                where OrderBy was declared to accept a
                Func<TSource,Fu nc<TSource,TKey >instead, I think it would cope just
                fine.
                How would that work? As you wrote before (maybe not in so many words, but
                I think it was basically the same thing), there's the issue of being able
                to use a Func<TSource, TKeyas a comparison object. Unless Func<TSource,
                TKeyimplemented IComparable (or whatever the "orderby" requirement
                happens to be), would that actually work? (Actually, now that I've played
                with the casting variations -- see below -- I think it wouldn't, or elseI
                misunderstand what you're saying).
                >I (think) I get why the compiler says what it says. Different parts of
                >the compiler are probably responsible for different parts of the
                >process;
                >there's effectively a pre-processor doing the "search and replace" part,
                >and by the time that then is tried to be compiled into IL, it's not only
                >just plain wrong, there's no enough type information for any inference
                >to
                >be done. Hence the actual error message.
                >
                Sort of. The query expression expansion part is indeed relatively
                plain. But I don't think that's the root cause - the root cause is the
                inability to infer a whole type directly from a lambda expression (as
                opposed to inferring some of the parameter types or the return type,
                based on knowledge of the general shape of what it's meant to be
                converted to).
                I guess we just differ on what we consider "the root cause". :) The way
                I'm looking at it, the lambda expression I originally tried has enough
                type information to be inferred, _if_ the context would match that type.
                But since the "search and replace" of the "orderby" statement causes the
                context to be something else, where the type information is no longer
                available, _that_'s the root cause. The act of incorporating my lambda
                expression into another one is the sequentially initial cause of the
                problem.

                I won't put words into your mouth, but my impression is that you're
                looking at the issue more from the point of the final compiler error, and
                why _that_ happens. To me, a "root cause" would be the "original point of
                failure", and to me that point of failure is the first point at which the
                type inference information is lost. It seems to me that to you, the
                "root" point of failure is found approaching the question from the other
                end: the compiler goes to try to match the arguments for OrderBy() and
                can't get past the lack of type information on the given lambda expression
                (the one generated by the "orderby" statement).

                It reminds me of the blackberry bushes I keep trying to whack back. They
                send out these leaders that burrow into the ground and create new root
                systems. At that point, which end is the "root" depends a lot on which
                direction you look. :)
                >So, sure...the cast is required...but the real gimmick in the code you
                >posted is the final "()" that actually _calls_ the delegate. That
                >changes
                >the lambda expression, after casting, into something that can then be
                >inserted into yet another lambda expression for actual evaluation. Even
                >with a cast, a lambda expression by itself wouldn't work.
                >
                It wouldn't actually *work*, but I think it would compile.
                Exactly right. :) I tried it. With the cast, the compiler decided it
                had enough type information to match the outer lambda expression and
                compiled fine. Of course, what it was returning was the delegate itself,
                not the evaluation of the delegate, and of course the delegate isn't
                comparable, so BOOM! :)
                [...]
                Just to be clear for any other readers - it's not "var" that creates
                anonymous types, it's expressions of the form new { Property =
                Value }.
                Thanks for the clarification. I understand where the anonymous type comes
                from, but I certainly didn't express myself very well.
                [...]
                However, yes, it would be possible for the compiler to create a new
                delegate type for you - or try to use one of the existing generic
                ones, as mentioned before. Personally I don't think the extra
                complexity in the language (particularly with respect to overloading -
                there are a few nasty cases I can think of off-hand) but I would
                imagine it would be doable.
                Before anonymous types, I would have said "sure, keep the language
                simple". But C# is getting much more complicated with each revision. If
                other people get their pet features, why not me? :)

                Pete

                Comment

                • Jon Skeet [C# MVP]

                  #9
                  Re: random sorting a collection

                  (Apologies for the previous duplication, btw. Network issues.)

                  I'm snipping a load of stuff here, just to get to interesting
                  things... a lot of the rest is just looking at things from different
                  points of view, and possibly a little miscommunicatio n. Nothing
                  particularly significant though.

                  On May 30, 8:08 am, "Peter Duniho" <NpOeStPe...@nn owslpianmk.com>
                  wrote:
                  If you wrote a type with the appropriate LINQ operators
                  where OrderBy was declared to accept a
                  Func<TSource,Fu nc<TSource,TKey >instead, I think it would cope just
                  fine.
                  >
                  How would that work? As you wrote before (maybe not in so many words, but
                  I think it was basically the same thing), there's the issue of being able
                  to use a Func<TSource, TKeyas a comparison object. Unless Func<TSource,
                  TKeyimplemented IComparable (or whatever the "orderby" requirement
                  happens to be), would that actually work? (Actually, now that I've played
                  with the casting variations -- see below -- I think it wouldn't, or else I
                  misunderstand what you're saying).
                  You could write your own ordering routine which first called the
                  "outer" function to return the "inner" function, then called the
                  "inner" function to return the sorting key.

                  I'm not saying it would be a particularly sane thing to do, but type
                  inference would cope (I believe).

                  <snip>
                  So, sure...the cast is required...but the real gimmick in the code you
                  posted is the final "()" that actually _calls_ the delegate. That
                  changes
                  the lambda expression, after casting, into something that can then be
                  inserted into yet another lambda expression for actual evaluation. Even
                  with a cast, a lambda expression by itself wouldn't work.
                  >
                  It wouldn't actually *work*, but I think it would compile.
                  >
                  Exactly right. :) I tried it. With the cast, the compiler decided it
                  had enough type information to match the outer lambda expression and
                  compiled fine. Of course, what it was returning was the delegate itself,
                  not the evaluation of the delegate, and of course the delegate isn't
                  comparable, so BOOM! :)
                  If it were possible to create a delegate type which implemented
                  IComparable<Tof course, that would be a different matter. Hmm...
                  interesting... it might be feasible with a bit of IL hackery.
                  [...]
                  However, yes, it would be possible for the compiler to create a new
                  delegate type for you - or try to use one of the existing generic
                  ones, as mentioned before. Personally I don't think the extra
                  complexity in the language (particularly with respect to overloading -
                  there are a few nasty cases I can think of off-hand) but I would
                  imagine it would be doable.
                  >
                  Before anonymous types, I would have said "sure, keep the language
                  simple". But C# is getting much more complicated with each revision. If
                  other people get their pet features, why not me? :)
                  :) I'd argue that as C# acquires more features, the bar for adding yet
                  another feature should be going up and up as well. I think the C# team
                  realise that in C# 3 they added quite a lot of stuff and need to let
                  it settle down for a while before they do too much more :)

                  But in terms of this particular feature, I think there's a big
                  difference between using an expression which is explicitly an
                  anonymous type, and using an expression which implicitly creates an
                  anonymous type just because of the way you've used it. Maybe I just
                  need to see more places it would be useful to convince me though :)

                  Jon

                  Comment

                  • Peter Duniho

                    #10
                    Re: random sorting a collection

                    On Fri, 30 May 2008 01:03:10 -0700, Jon Skeet [C# MVP] <skeet@pobox.co m>
                    wrote:
                    [...]
                    >How would that work? As you wrote before (maybe not in so many words,
                    >but
                    >I think it was basically the same thing), there's the issue of being
                    >able
                    >to use a Func<TSource, TKeyas a comparison object. Unless
                    >Func<TSource ,
                    >TKeyimplemente d IComparable (or whatever the "orderby" requirement
                    >happens to be), would that actually work? (Actually, now that I've
                    >played
                    >with the casting variations -- see below -- I think it wouldn't, or
                    >else I
                    >misunderstan d what you're saying).
                    >
                    You could write your own ordering routine which first called the
                    "outer" function to return the "inner" function, then called the
                    "inner" function to return the sorting key.
                    >
                    I'm not saying it would be a particularly sane thing to do, but type
                    inference would cope (I believe).
                    I see. Yes, seems icky to me. :)
                    [...]
                    But in terms of this particular feature, I think there's a big
                    difference between using an expression which is explicitly an
                    anonymous type, and using an expression which implicitly creates an
                    anonymous type just because of the way you've used it. Maybe I just
                    need to see more places it would be useful to convince me though :)
                    Well, for me the most obvious example is the Control.Invoke( ) method,
                    which is used on a very regular basis. Casting works fine, of course, but
                    the casting is always to some arbitrary type that the Invoke() method
                    itself doesn't really care about anyway.

                    Other than that, I admit...I don't run into the issue much, if at all.
                    Most of the time, for a delegate there's a very specific signature and an
                    explicit type needed that the compiler can use for inference. I guess the
                    question becomes, to some extent, is frequency of use sufficient cause, or
                    does there need to be a threshold met of variety of use as well.

                    I'm happy to leave that debate up to the language designers. I've done
                    great by them so far, and I'm not about to mess with a good thing (even if
                    I could, which I can't :) ).

                    Pete

                    Comment

                    • Jon Skeet [C# MVP]

                      #11
                      Re: random sorting a collection

                      Peter Duniho <NpOeStPeAdM@nn owslpianmk.comw rote:
                      I'm not saying it would be a particularly sane thing to do, but type
                      inference would cope (I believe).
                      >
                      I see. Yes, seems icky to me. :)
                      Oh indeed. There are lots of "fun" (read: evil) things you can do to
                      query expression syntax. At one geek night we even started creating
                      anonymous types with properties called "Select", "Where" etc which were
                      of suitable delegate types... the query expression expansion worked
                      fine with them. Totally useless, of course, but fun.
                      [...]
                      But in terms of this particular feature, I think there's a big
                      difference between using an expression which is explicitly an
                      anonymous type, and using an expression which implicitly creates an
                      anonymous type just because of the way you've used it. Maybe I just
                      need to see more places it would be useful to convince me though :)
                      >
                      Well, for me the most obvious example is the Control.Invoke( ) method,
                      which is used on a very regular basis. Casting works fine, of course, but
                      the casting is always to some arbitrary type that the Invoke() method
                      itself doesn't really care about anyway.
                      Just as a thought, I wonder what would happen if you added an extension
                      method to Control.Invoke taking a MethodInvoker (and then calling the
                      "real" Control.Invoke with it)... that might well work around the
                      problem quite easily.
                      Other than that, I admit...I don't run into the issue much, if at all.
                      Most of the time, for a delegate there's a very specific signature and an
                      explicit type needed that the compiler can use for inference. I guess the
                      question becomes, to some extent, is frequency of use sufficient cause, or
                      does there need to be a threshold met of variety of use as well.
                      >
                      I'm happy to leave that debate up to the language designers. I've done
                      great by them so far, and I'm not about to mess with a good thing (even if
                      I could, which I can't :) ).
                      :) Yup, they've done a very good job so far. I'm still not wild about
                      the way extension methods are discovered, and I wish that classes were
                      sealed by default, but hey...

                      --
                      Jon Skeet - <skeet@pobox.co m>
                      Web site: http://www.pobox.com/~skeet
                      Blog: http://www.msmvps.com/jon.skeet
                      C# in Depth: http://csharpindepth.com

                      Comment

                      • Adam Sandler

                        #12
                        Re: random sorting a collection

                        Thanks everyone for the assistance!

                        Comment

                        Working...