Passing null as an "out" parameter

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • John Layton

    #1

    Passing null as an "out" parameter

    Hi there,

    Is it possible to pass null to a function taking an "out" (or "ref")
    parameter in C#. I'd like to do something like the following (which doesn't
    compile of course). Thanks in advance.

    int SomeValue;
    Func(null, SomeValue); // Any way to pass null for either arg?

    void Func(out int Param1, out int Param2)
    {
    if (Param1 != null)
    {
    Param1 = Whatever1();
    }

    if (Param2 != null)
    {
    Param2 = Whatever2();
    }
    }


  • Paul E Collins

    #2
    Re: Passing null as an "out&qu ot; parameter

    I don't think this is an out vs. ref issue...

    Your code won't compile in C# 1.x because null is only an acceptable
    value for reference types (ones based on a class, rather than anything
    like int, float, or a struct). I'm not overly familiar with the C# 2.0
    compiler, but I believe it'll let you have nullable value types if you
    append ? to the type name. Does your code work if you use "int?"
    rather than "int" ?

    Eq.


    Comment

    • Marc Gravell

      #3
      Re: Passing null as an "out&qu ot; parameter

      Well, since you look at the values inside the method, you probably mean
      "ref", in which case something like:
      int? binMe = null, someValue = 0;
      Func(ref binMe, ref someValue); // Any way to pass null for either arg?
      Console.WriteLi ne(binMe);
      Console.WriteLi ne(someValue);
      static void Func(ref int? Param1, ref int? Param2) {
      if (Param1 != null) Param1 = 7; // random
      if (Param2 != null) Param2 = 5; // random
      }

      It *looks* like you are trying to decide which values to lookup (perhaps
      from a DB); in which case, another option is some kind of bitmask, perhaps
      in a [Flags] enum.


      Comment

      • John Layton

        #4
        Re: Passing null as an "out&qu ot; parameter

        I don't think this is an out vs. ref issue...
        >
        Your code won't compile in C# 1.x because null is only an acceptable value
        for reference types (ones based on a class, rather than anything like int,
        float, or a struct). I'm not overly familiar with the C# 2.0 compiler, but
        I believe it'll let you have nullable value types if you append ? to the
        type name. Does your code work if you use "int?" rather than "int" ?
        Thanks for the response. Perhaps it was a bad example then since the args
        will be reference types in practice (I'm coming from the C++ world where no
        such issues exist). If they are reference types then is this doable? Thanks
        again.


        Comment

        • John Layton

          #5
          Re: Passing null as an "out&qu ot; parameter

          "Marc Gravell" <marc.gravell@g mail.comwrote in message
          news:uxIKausxGH A.1304@TK2MSFTN GP05.phx.gbl...
          Well, since you look at the values inside the method, you probably mean
          "ref", in which case something like:
          int? binMe = null, someValue = 0;
          Func(ref binMe, ref someValue); // Any way to pass null for either arg?
          Console.WriteLi ne(binMe);
          Console.WriteLi ne(someValue);
          static void Func(ref int? Param1, ref int? Param2) {
          if (Param1 != null) Param1 = 7; // random
          if (Param2 != null) Param2 = 5; // random
          }
          >
          It *looks* like you are trying to decide which values to lookup (perhaps
          from a DB); in which case, another option is some kind of bitmask, perhaps
          in a [Flags] enum.
          Thanks for the response. I'm not sure what the "?" in "int?" does however
          (haven't seen this before but will look it up). In any event, passing bit
          flags is inconvenient :) In the general case, when one has a function that
          returns multiple out arguments and a client is only interested in a subset
          of them, the ability to simply pass "null" for the others is very convenient
          (and saves you from having to declare variables unnecessarily).


          Comment

          • Bruce Wood

            #6
            Re: Passing null as an &quot;out&qu ot; parameter


            John Layton wrote:
            "Marc Gravell" <marc.gravell@g mail.comwrote in message
            news:uxIKausxGH A.1304@TK2MSFTN GP05.phx.gbl...
            Well, since you look at the values inside the method, you probably mean
            "ref", in which case something like:
            int? binMe = null, someValue = 0;
            Func(ref binMe, ref someValue); // Any way to pass null for either arg?
            Console.WriteLi ne(binMe);
            Console.WriteLi ne(someValue);
            static void Func(ref int? Param1, ref int? Param2) {
            if (Param1 != null) Param1 = 7; // random
            if (Param2 != null) Param2 = 5; // random
            }

            It *looks* like you are trying to decide which values to lookup (perhaps
            from a DB); in which case, another option is some kind of bitmask, perhaps
            in a [Flags] enum.
            >
            Thanks for the response. I'm not sure what the "?" in "int?" does however
            (haven't seen this before but will look it up). In any event, passing bit
            flags is inconvenient :) In the general case, when one has a function that
            returns multiple out arguments and a client is only interested in a subset
            of them, the ability to simply pass "null" for the others is very convenient
            (and saves you from having to declare variables unnecessarily).
            The short answer: no.

            However, there is a way to use Marc's bit masks but not pollute your
            client code. It involves writing a lot of overloads, and won't work if
            several (or all) of your arguments are the same type, but what about
            this:

            [Flags]
            private enum ReturnType = {
            ReturnCustomer = 0x01,
            ReturnSupplier = 0x02,
            ...
            };

            private void Fetch(ReturnTyp e whatToReturn, out Customer cust, out
            Supplier supp)
            {
            if ((whatToReturn & ReturnType.Retu rnCustomer) != 0)
            {
            cust = ... ;
            }
            if ((whatToReturn & ReturnType.Retu rnSupplier) != 0)
            {
            supp = ... ;
            }
            }

            public void Fetch(out Customer cust, out Supplier supp)
            {
            Fetch(ReturnTyp e.Customer | ReturnType.Supp lier, out cust, out
            supp);
            }

            public void Fetch(out Customer cust)
            {
            Supplier dummySupplier;
            Fetch(ReturnTyp e.Customer, out cust, out dummySupplier);
            }

            public void Fetch(out Supplier supp)
            {
            Customer dummyCustomer;
            Fetch(ReturnTyp e.Supplier, out dummyCustomer, out supp);
            }

            As I said, it doesn't work for all scenarios, but it does hide the
            declaration of unnecessary variables inside overloaded methods.

            Comment

            • John Layton

              #7
              Re: Passing null as an &quot;out&qu ot; parameter

              Thanks for the suggestion. It looks like I have little choice but it's a
              pain IMO :) Anyway, thanks again.


              Comment

              • Marc Gravell

                #8
                Re: Passing null as an &quot;out&qu ot; parameter

                "int?" is a C# shortcut for the 2.0 generic (immutable) struct
                Nullable<int>; Nullable<T(in general) sports a struct T and a bool
                (.HasValue) to indicate if it has a value or should be considered null. Note
                that since it is a struct it never really *is* null (in the object sense),
                but that the compiler infers null equality via the .HasValue property.

                Note, however, that you could achieve a similar effect in 1.1 using "magic
                numbers", such as int.MinValue to mean "ignore this".

                To be honest, however, I'm not really loving this whole approach anyway - it
                seems (more than) a bit unsightly; perhaps I'd go for something a whole lot
                simpler (ignore names):

                public class SomethingResult { // or struct, depending
                public int SomeValue;
                public float SomeOtherValue;
                public bool SomethingElse;
                }

                [Flags]
                pulic enum QueryOptions {
                None = 0, SomeValue = 1, SomeOtherValue = 2, SomethingElse = 4, All = 7
                }

                public SomethingResult DoSomething(Que ryOptions options) {
                SomethingResult result = new SomethingResult ();
                if((options & QueryOptions.So meValue) == QueryOptions.So meValue)
                result.SomeValu e = // do something
                if((options & QueryOptions.So meOtherValue) == QueryOptions.So meOtherValue)
                result.SomeOthe rValue= // do something
                if((options & QueryOptions.So methingElse ) == QueryOptions.So methingElse)
                result.Somethin gElse = // do something
                }

                You can now just call DoSomething() specifying what you want, and then
                inspect the returned object to get the values (only looking at the ones you
                asked for; the rest will default to null/0/false). No hastle with ref / out;
                no setting up 20 dummy parameters just because you want to read one value;
                very friendly, and compatible with both 1.1 and 2.0 runtimes.

                Marc



                Comment

                Working...