Debug.Assert

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Peter Morris

    Debug.Assert

    In Delphi I used to use Assert as a development aid. During debug it would
    ensure that certain conditions were met but in the Release build the Asserts
    were not compiled into the application. I am assuming this is the same with
    ..NET too? Debug.Assert isn't compiled into a Release build?

    The other thing I am curious about is this

    public void DoSomething(Per son p)
    {
    if (p == null)
    throw new ArgumentNullExc eption("P");
    ....
    }

    Why do people tend to use exceptions such as ArgumentNullExc eption instead
    of something like this which I presume gets skipped in Release build and is
    also quicker to type?

    public void DoSomething(Per son p)
    {
    Debug.Assert(p != null, "P is null");
    ....
    }



    Pete


  • Marc Gravell

    #2
    Re: Debug.Assert

    Debug.Assert is marked with [Conditional("DE BUG")], which means that
    calls to it only get compiled if the caller has the DEBUG symbol defined.

    So yes; calls to Debug.Assert will not be compiled into a release build,
    as long as you don't define "DEBUG" ;-p

    Re the null check; Well, I guess it depends on what the code is. If it
    is a library you can't trust the caller, so you'd need to still check.
    For UI work, you could argualy use an Assert, but you'd need to be sure
    that you have 100% code coverage. But this check will be ridiculously
    quick, so I'd probably leave it in in most cases.

    Re typing, well, you could probably use a custom snippet if you
    wanted... in C# 3 you could also use an extension method (confusing
    fact: you can call extension methods on null instances) - so you might have:

    person.ThrowIfN ull("person");

    (note I renamed the variable to be meaningful; I'd recommend this...
    it'll save pain in the long run).

    Marc

    Comment

    • Larry Smith

      #3
      Re: Debug.Assert

      Why do people tend to use exceptions such as ArgumentNullExc eption instead
      of something like this which I presume gets skipped in Release build and
      is also quicker to type?
      >
      public void DoSomething(Per son p)
      {
      Debug.Assert(p != null, "P is null");
      ....
      }
      It really boils down to whether it's something that can happen in your
      release build or not. If you're serving up a release library to a 3rd party
      in particular then you never know what someone might pass. OTOH, if it's
      only being consumed by your own code, then an "Assert()" is usually fine
      IMO. Some would still argue that an exception should be used however if only
      to catch your own mistakes (those that make it into the release build by
      accident). In my long experience however, I don't recall ever encountering
      this situation. I therefore rely on "Assert()" extensively for all my own
      code. Maybe it's not quite as safe, but relying on exceptions to catch
      programmer errors in a release build just rubs me the wrong way. GIGO should
      be understood by developers who need to apply diligence when they program.
      An "Assert()" is normally sufficient for this IMO (even for 3rd party
      developers for that matter) but it's really a personal choice.


      Comment

      • Peter Morris

        #4
        Re: Debug.Assert

        Those were the rules I have imposed on myself in the past, so I am pleased
        to see a couple of replies confirming that I am doing the right thing :-)
        (note I renamed the variable to be meaningful; I'd recommend this... it'll
        save pain in the long run).
        I am more idle when writing in newsgroups ;-)


        Thanks

        Pete

        Comment

        • Pavel Minaev

          #5
          Re: Debug.Assert

          On Aug 1, 3:26 pm, Marc Gravell <marc.grav...@g mail.comwrote:
          Re the null check; Well, I guess it depends on what the code is. If it
          is a library you can't trust the caller, so you'd need to still check.
          For UI work, you could argualy use an Assert, but you'd need to be sure
          that you have 100% code coverage. But this check will be ridiculously
          quick, so I'd probably leave it in in most cases.
          Technically, there's also a third option - Trace.Assert, which is in
          release builds by default.

          Even so, using ArgumentExcepti on is the standard .NET pattern, and I
          don't see any good reason for avoiding it (saving 3 lines of code is
          not a good reason). Also, VS Code Analysis has an option to enforce
          validation of arguments, and the only way it supports is explicit
          check and throw ArgumentNullExc eption.

          Comment

          • Marc Gravell

            #6
            Re: Debug.Assert

            I know it has been discussed before, but a language tweak would be very
            welcome here; something like:

            public void DoSomething(Per son !p) {...}

            And let the compiler worry about it.

            (although perhaps more meaningful syntax)

            Comment

            • Jon Skeet [C# MVP]

              #7
              Re: Debug.Assert

              On Aug 1, 2:00 pm, Marc Gravell <marc.grav...@g mail.comwrote:
              I know it has been discussed before, but a language tweak would be very
              welcome here; something like:
              >
              public void DoSomething(Per son !p) {...}
              >
              And let the compiler worry about it.
              >
              (although perhaps more meaningful syntax)
              I'd go for "Person! person" to mirror "int? value".
              Mads and I discussed this a bit back in 2005. It's the obvious "4th
              box" to fill in for the value/reference, nullable/non-nullable matrix.

              I'd be happy if it were just a shortcut for automatically creating
              null-checking code at the start of methods, even without the
              "correctnes s proving" which would also be possible.

              Jon

              Comment

              • Marc Gravell

                #8
                Re: Debug.Assert

                Yes, that makes a lot more sense.

                Marc\

                Comment

                • Peter Morris

                  #9
                  Re: Debug.Assert

                  I've seen (somewhere) an example of using something like PostSharp to
                  enforce it

                  [NotNull<Person> ("person")]
                  public void DoSomething(Per son person)
                  {
                  }

                  But at best it makes me mmm and ahhh a bit, doesn't jump out at me as a
                  great solution.

                  Comment

                  • Alun Harford

                    #10
                    Re: Debug.Assert

                    Marc Gravell wrote:
                    Debug.Assert is marked with [Conditional("DE BUG")], which means that
                    calls to it only get compiled if the caller has the DEBUG symbol defined.
                    >
                    So yes; calls to Debug.Assert will not be compiled into a release build,
                    as long as you don't define "DEBUG" ;-p
                    >
                    Re the null check; Well, I guess it depends on what the code is. If it
                    is a library you can't trust the caller, so you'd need to still check.
                    For UI work, you could argualy use an Assert, but you'd need to be sure
                    that you have 100% code coverage. But this check will be ridiculously
                    quick, so I'd probably leave it in in most cases.
                    >
                    Re typing, well, you could probably use a custom snippet if you
                    wanted... in C# 3 you could also use an extension method (confusing
                    fact: you can call extension methods on null instances) - so you might
                    have:
                    >
                    person.ThrowIfN ull("person");
                    I wrote an evil little extension method a while ago:

                    [MethodImpl(Meth odImplOptions.N oInlining)]
                    public static void CheckForNull(th is object o)
                    {
                    if (o != null) return;
                    StackFrame frame = new StackFrame(1, true);
                    byte op =
                    frame.GetMethod ().GetMethodBod y().GetILAsByte Array()[frame.GetILOffs et()
                    - 6];
                    throw new
                    ArgumentNullExc eption(frame.Ge tMethod().GetPa rameters().Leng th <=
                    (4 - (frame.GetMetho d().IsStatic ? 0 : 1)) ?
                    frame.GetMethod ().GetParameter s()[op - (2 +
                    (frame.GetMetho d().IsStatic ? 0 : 1))].Name :
                    "An argument was null, but I'm not sure which one.");
                    }

                    No need to pass the parameter name.

                    Alun Harford

                    Comment

                    • Alun Harford

                      #11
                      Re: Debug.Assert

                      Jon Skeet [C# MVP] wrote:
                      On Aug 1, 2:00 pm, Marc Gravell <marc.grav...@g mail.comwrote:
                      >I know it has been discussed before, but a language tweak would be very
                      >welcome here; something like:
                      >>
                      >public void DoSomething(Per son !p) {...}
                      >>
                      >And let the compiler worry about it.
                      >>
                      >(although perhaps more meaningful syntax)
                      >
                      I'd go for "Person! person" to mirror "int? value".
                      This is exactly what Spec# uses. I *really* want that in C# 4 (or a C#3
                      version of Spec#)

                      Alun Harford

                      Comment

                      Working...