params (rant)

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • =?Utf-8?B?UElFQkFMRA==?=

    params (rant)

    Given a method like

    void F ( params object[] args ) { ... }

    I had always _assumed_ that args would never be null, but now it's been
    brought to my attention that if the caller uses

    F ( null )

    then args _will_ be null because the compiler can implicitly convert the
    null to an object[].

    But I doubt that this is the desired behaviour in most cases, certainly _I_
    expect (and prefer) args to be an array containing one null, just as

    F ( null , null )

    results in an array containing two nulls.

    Some experimentation has shown that

    F ( new object[] { null } )
    and
    F ( (object) null )

    result in the desired array, but the caller shouldn't have to go through
    such hoops.

    It seems to me that rather than have the compiler see if the value can be
    implicitly converted to the array type, it shoud determine if the value _is_
    the array type.


    I realize that it's too late to change the language, and if someone _does_
    want the parameter to be null, then the current behaviour seems the only way.
    But, man, now I have to go through my code looking for methods that take
    params and protect against null.

  • Jon Skeet [C# MVP]

    #2
    Re: params (rant)

    PIEBALD <PIEBALD@discus sions.microsoft .comwrote:
    Given a method like
    >
    void F ( params object[] args ) { ... }
    >
    I had always _assumed_ that args would never be null, but now it's been
    brought to my attention that if the caller uses
    >
    F ( null )
    >
    then args _will_ be null because the compiler can implicitly convert the
    null to an object[].
    Indeed. params *allows* the caller to use the F(x, y, z) syntax, but it
    doesn't *force* it.
    But I doubt that this is the desired behaviour in most cases, certainly _I_
    expect (and prefer) args to be an array containing one null, just as
    >
    F ( null , null )
    >
    results in an array containing two nulls.
    Note that this will only be the behaviour when you're using the
    *literal* null. If you do:

    object o = null;
    F(o);

    or something similar, that will be handled as you expect. I think it's
    relatively rare to need to call a method with params parameter passing
    a null literal - and given that you might *also* want to call it
    passing a null argument instead of an array containing a null value,
    the language has to make a trade-off anyway.
    It seems to me that rather than have the compiler see if the value can be
    implicitly converted to the array type, it shoud determine if the value _is_
    the array type.
    I disagree. I think it's fine the way it is.
    I realize that it's too late to change the language, and if someone _does_
    want the parameter to be null, then the current behaviour seems the only way.
    But, man, now I have to go through my code looking for methods that take
    params and protect against null.
    You should have done so anyway - or at least expected that the value
    could be null. After all, you could have:

    object[] x = null;
    F(x);

    Are you surprised that the above compiles? If not, what would you have
    expected it to do?

    --
    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

    • =?Utf-8?B?UElFQkFMRA==?=

      #3
      Re: params (rant)

      You should have done so anyway

      So it seems.

      Comment

      • Peter Duniho

        #4
        Re: params (rant)

        On Sun, 28 Sep 2008 11:22:37 -0700, Jon Skeet [C# MVP] <skeet@pobox.co m>
        wrote:
        [...]
        >But, man, now I have to go through my code looking for methods that take
        >params and protect against null.
        >
        You should have done so anyway - or at least expected that the value
        could be null. After all, you could have:
        >
        object[] x = null;
        F(x);
        >
        Are you surprised that the above compiles? If not, what would you have
        expected it to do?
        For what it's worth, I think part of the issue is that people coming from
        C++ may be viewing the "params" argument declaration to work like C++'s
        variable-length argument list, in that you never have direct access to the
        list itself when using the standard parameter list syntax.

        With that perspective, I think one could expect your example to compile to
        a single-element parameter list with the value of "null" as that element.
        In other words, the parameter array would still not be null; it would
        _contain_ a null.

        I realize that's just not how C# works, but it would have been a
        reasonable design, at least ignoring other side-effects and complexities
        it would introduce to C#.

        Pete

        Comment

        • Jon Skeet [C# MVP]

          #5
          Re: params (rant)

          On Sep 29, 12:04 am, "Peter Duniho" <NpOeStPe...@nn owslpianmk.com>
          wrote:

          <snip>
          With that perspective, I think one could expect your example to compile to a single-element parameter list with the value of "null" as that element.  
          In other words, the parameter array would still not be null; it would  
          _contain_ a null.
          Good point. Here's a clearer example, without the ambiguity stemming
          from the fact that object[] can be converted to object:

          void Foo(params string[] args)
          {
          }
          ....
          string[] x = null;
          Foo(x);

          Clearly that can't be treating x as a string, because it's a string[].
          Therefore if the above compiles, it's possible for a "params"
          parameter to be null. Therefore one should check "params" parameters
          for nullity in the same way as other parameters.

          The only argument against that would be if the OP wouldn't have
          expected the above code to compile - which would be a horrible
          restriction, IMO.

          Jon

          Comment

          • Peter Duniho

            #6
            Re: params (rant)

            On Sun, 28 Sep 2008 23:13:45 -0700, Jon Skeet [C# MVP] <skeet@pobox.co m>
            wrote:
            [...]
            Good point. Here's a clearer example, without the ambiguity stemming
            from the fact that object[] can be converted to object:
            >
            void Foo(params string[] args)
            {
            }
            ...
            string[] x = null;
            Foo(x);
            >
            Clearly that can't be treating x as a string, because it's a string[].
            Therefore if the above compiles, it's possible for a "params"
            parameter to be null. Therefore one should check "params" parameters
            for nullity in the same way as other parameters.
            Well, yes. I agree with the basic logic. But trying to apply it in a
            practical sense is difficult. After all, to do so assumes that the OP
            would have written a bit of test code like that, just to see what was
            legal and what wasn't.

            I admit, I find myself doing that sort of thing, and it wouldn't surprise
            me if you do too. But it's hardly the sort of thing I expect every
            developer to do as part of their normal development process.

            I do it because I like the peek inside the box to see what's making things
            tick (okay, it's more like toppling the stack of presents Mom tried to
            hide on the shelf, and then shaking them vigorously...bu t whatever :) ).
            But lots of programmers just want to get the job done, and don't have the
            inclination and/or time to mess around with poking and prodding the
            compiler to explore the corner cases.

            In particular, in this case I think had it occurred to the OP to write
            test code like the above, he probably would have just tested the "passing
            null directly" case to see what happens.

            I don't know what the OP's true feelings are on the question (that is, is
            he actually mad at the language, or was he just frustrated for a moment),
            but at the very least, I can see why he felt a need to blow off a little
            steam with his rant. :)
            The only argument against that would be if the OP wouldn't have
            expected the above code to compile - which would be a horrible
            restriction, IMO.
            "Horrible"? I don't know. I mean, I do appreciate the C# implementation
            of variable-length parameter lists. But other languages get by just
            fine. If anything, because of the way C# does it, in reality it really is
            just glossy syntax on top of a very basic idea: passing an array.

            Had C# prohibited the example you offer here, I don't think it'd be that
            big of a deal. You just couldn't use variable-length parameter lists in a
            scenario where what you really wanted to pass was a reference to an array,
            possibly null. You'd have to declare and use it more explicitly. No big
            deal, at least for me it wouldn't be.

            Pete

            Comment

            • Marc Gravell

              #7
              Re: params (rant)

              And once again I find myself yearning for the missing "argument cannot
              be null" language feature. Maybe one day...

              Marc

              Comment

              • Pavel Minaev

                #8
                Re: params (rant)

                On Sep 28, 10:22 pm, Jon Skeet [C# MVP] <sk...@pobox.co mwrote:
                You should have done so anyway - or at least expected that the value
                could be null. After all, you could have:
                >
                object[] x = null;
                F(x);
                >
                Are you surprised that the above compiles? If not, what would you have
                expected it to do?
                I think the problem here is that when checking for null params, one
                could reasonably think that just throwing ArgumentNullExc eption would
                be fine (because it handles the case above). But then it can puzzle
                the client, who can do:

                F(null);

                and get an ArgumentNullExc eption on that, but not on:

                F(null, null);

                which is certainly rather confusing.

                Comment

                • Jon Skeet [C# MVP]

                  #9
                  Re: params (rant)

                  On Sep 29, 7:35 am, "Peter Duniho" <NpOeStPe...@nn owslpianmk.com>
                  wrote:

                  <snip>
                  "Horrible"?  I don't know.  I mean, I do appreciate the C# implementation  
                  of variable-length parameter lists.  But other languages get by just  
                  fine.  If anything, because of the way C# does it, in reality it reallyis  
                  just glossy syntax on top of a very basic idea: passing an array.
                  >
                  Had C# prohibited the example you offer here, I don't think it'd be that  
                  big of a deal.  You just couldn't use variable-length parameter lists in a  
                  scenario where what you really wanted to pass was a reference to an array,  
                  possibly null.  You'd have to declare and use it more explicitly.  Nobig  
                  deal, at least for me it wouldn't be.
                  I think it would have been a significant limitation. For instance,
                  consider this exception constructor:

                  public MyException (string format, params object[] args) :
                  base(string.For mat(format, args))
                  {
                  ...
                  }

                  I use that kind of thing reasonably often - I like to be able to make
                  it easy for callers to format text without explicitly calling
                  string.Format themselves. However, the restriction above would prevent
                  *my* code from calling string.Format. We'd potentially have to have
                  overloads for everything - string.Format(s tring, object[]),
                  string.Format(s tring, params object[]) which just ends up being silly
                  IMO. It would also rely on everyone who implemented a method with a
                  "params" parameter being considerate enough to provide the overload.

                  Jon

                  Comment

                  • Peter Duniho

                    #10
                    Re: params (rant)

                    On Mon, 29 Sep 2008 00:23:58 -0700, Jon Skeet [C# MVP] <skeet@pobox.co m>
                    wrote:
                    On Sep 29, 7:35 am, "Peter Duniho" <NpOeStPe...@nn owslpianmk.com>
                    wrote:
                    >
                    <snip>
                    >
                    >"Horrible"?  I don't know.  [...]
                    >
                    I think it would have been a significant limitation.
                    I'm going to go with "eye of the beholder" here.
                    For instance,
                    consider this exception constructor:
                    >
                    public MyException (string format, params object[] args) :
                    base(string.For mat(format, args))
                    {
                    ...
                    }
                    >
                    I use that kind of thing reasonably often - I like to be able to make
                    it easy for callers to format text without explicitly calling
                    string.Format themselves. However, the restriction above would prevent
                    *my* code from calling string.Format. [...]
                    Not necessarily. C# could just provide a syntax that allows for a
                    different mechanism to forward variable-length parameter lists. After
                    all, that's what C++ does.

                    But in any case, while I don't disagree with your example, I do disagree
                    with the claim of seriousness. It's inconvenient, to be sure. But
                    "horrible"? I remain unconvinced that it rises to that level of badness.
                    :)

                    Pete

                    Comment

                    Working...