Nullable types in a constructor?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Steven Livingstone

    #1

    Nullable types in a constructor?

    Bit of advice here folks.

    I am creating a default constructor that just initializes a new instance of
    my object and a secon constructor that takes an ID and loads an object with
    data from the database for the given ID. I could just leave two separate
    constructors, or i could just have the default one call the second with a
    "-1" as the ID. This means that the initialization of certain fields can be
    based on whether my ID is -1 (for lazy loading and so on).

    Here is my question.... i'd like to make use of a nullable int in this case,
    so rather than passing -1 as my default value when calling the second
    constructor from the first, i can pass null.

    Is this good practice, especially in public constructors/interfaces to use
    int? (realize how hard it is to end this sentence with a question mark now -
    but it IS a question!! :)

    Here is a rough example of what i'm harping on about (for a class "Element")
    ........

    public Element() : this(null) { }

    public Element(int? elementid)
    {
    InitializeObjec t();

    if (elementid != null)
    SetUpObject(ele mentid);
    }

    The alternative is to use -1 in public interfaces and use null internally,
    but that's kinda daft. I'd rather be consistent with one or the other. In
    other words, for a number of the constructors that i DO have, which all are
    public, can i (or is it a good idea to) use int? and so on rather than the
    traditional int??

    At a more advanced level - is it part of the CLI? Are there limitations i am
    going to run into?
    What kind of support with web services, wsdl, schema (well xml schema doe
    support null's) as generated from .Net is there for int?

    thanks,
    steven :: http://stevenR2.com


  • Jon Skeet [C# MVP]

    #2
    Re: Nullable types in a constructor?

    Steven Livingstone wrote:[color=blue]
    > Bit of advice here folks.
    >
    > I am creating a default constructor that just initializes a new instance of
    > my object and a secon constructor that takes an ID and loads an object with
    > data from the database for the given ID. I could just leave two separate
    > constructors, or i could just have the default one call the second with a
    > "-1" as the ID. This means that the initialization of certain fields can be
    > based on whether my ID is -1 (for lazy loading and so on).
    >
    > Here is my question.... i'd like to make use of a nullable int in this case,
    > so rather than passing -1 as my default value when calling the second
    > constructor from the first, i can pass null.
    >
    > Is this good practice, especially in public constructors/interfaces to use
    > int? (realize how hard it is to end this sentence with a question mark now -
    > but it IS a question!! :)[/color]

    I think it depends on the context, as you rightly questioned later.

    I wouldn't use a generic type (which nullable types are) in any
    web-service definitions - that's just asking for trouble. I'm not
    saying they won't work, but it sounds like a bad idea to me.

    Nullable types appear to be CLS-compliant, in that that compiler
    doesn't complain about a type with a constructor taking an int?
    parameter, so I would feel comfortable using it for anything which
    doesn't need to interoperate with other platforms.

    Jon

    Comment

    • Steven Livingstone

      #3
      Re: Nullable types in a constructor?

      Thanks Jon -

      that's not too bad - it is typical that my web service interfaces sit as a
      layer on top of my business services layer anyway.
      I can make -1 a null at that point i guess.

      Hmmmm - whilst writing read a little and ran a test. .Net uses xsi:nil for
      nullable value types in serialization.

      The WSDL interface that is generated can use xsi:nil for elements i defined
      to be nullable value types
      in my interface!? That would make it pretty cross platform i would hope.

      That makes things a little easier i guess and definitely encourages me to
      use them!

      steven :: http://stevenR2.com

      "Jon Skeet [C# MVP]" <skeet@pobox.co m> wrote in message
      news:1138275669 .565604.177470@ f14g2000cwb.goo glegroups.com.. .[color=blue]
      > Steven Livingstone wrote:[color=green]
      >> Bit of advice here folks.
      >>
      >> I am creating a default constructor that just initializes a new instance
      >> of
      >> my object and a secon constructor that takes an ID and loads an object
      >> with
      >> data from the database for the given ID. I could just leave two separate
      >> constructors, or i could just have the default one call the second with a
      >> "-1" as the ID. This means that the initialization of certain fields can
      >> be
      >> based on whether my ID is -1 (for lazy loading and so on).
      >>
      >> Here is my question.... i'd like to make use of a nullable int in this
      >> case,
      >> so rather than passing -1 as my default value when calling the second
      >> constructor from the first, i can pass null.
      >>
      >> Is this good practice, especially in public constructors/interfaces to
      >> use
      >> int? (realize how hard it is to end this sentence with a question mark
      >> now -
      >> but it IS a question!! :)[/color]
      >
      > I think it depends on the context, as you rightly questioned later.
      >
      > I wouldn't use a generic type (which nullable types are) in any
      > web-service definitions - that's just asking for trouble. I'm not
      > saying they won't work, but it sounds like a bad idea to me.
      >
      > Nullable types appear to be CLS-compliant, in that that compiler
      > doesn't complain about a type with a constructor taking an int?
      > parameter, so I would feel comfortable using it for anything which
      > doesn't need to interoperate with other platforms.
      >
      > Jon
      >[/color]


      Comment

      • Jon Skeet [C# MVP]

        #4
        Re: Nullable types in a constructor?

        Steven Livingstone wrote:[color=blue]
        > that's not too bad - it is typical that my web service interfaces sit as a
        > layer on top of my business services layer anyway.
        > I can make -1 a null at that point i guess.
        >
        > Hmmmm - whilst writing read a little and ran a test. .Net uses xsi:nil for
        > nullable value types in serialization.
        >
        > The WSDL interface that is generated can use xsi:nil for elements i defined
        > to be nullable value types
        > in my interface!? That would make it pretty cross platform i would hope.
        >
        > That makes things a little easier i guess and definitely encourages me to
        > use them![/color]

        Well, I wouldn't assume it'll work cross-platform without trying it. At
        the very least, try consuming the web service from Java - see what
        comes out. In fact, Java may well cope by using java.lang.Integ er
        (which is a reference type) rather than "int". Just don't forget that
        it's not a case of what can go across SOAP/whatever, but also what
        languages can consume that WSDL to generate the right requests.

        Jon

        Comment

        • Steven Livingstone

          #5
          Re: Nullable types in a constructor?

          This post started as a few lines and expanded to some off topic thoughts on
          my frustrations with nullable value types - please comment if you wish and
          i blogged it here :


          I have to say working with these things is a little irritating. Mainly
          because you can't go implcitly from int? to int and so although in the
          context of your Entity you may allow a null ID, the concept of a null ID may
          NOT be something you wish to expose to method calls using the object or at
          least avoid you having to type everything int? and then check hasValue.

          Here's is what I am talking about.

          You define a simple element entity as follows:

          public class Element
          {
          int? _id = null;

          public int? ID
          {
          get { return _id;}
          set {_id=value;}
          }
          }


          You then may have a data object as follows:

          public class MyData
          {
          public void Save(Element element)
          {
          if (element.ID == null)
          SaveNew(...);
          else
          Update(...);
          }
          }

          The issue you now have is that any business methods, helper methods and so
          on that use this ID can then expect two types of query. The first is where
          you have a valid ID (number > 0) and the second is where you have a null
          value. Therefore, everytime you want to call a method such as the following,
          which will pass the ID of the element to the method you ALWAYS have to do
          hasValue.

          public class MyBusiness
          {
          public void AttachToItem(in t? id)
          {
          if (!id.hasValue)
          throw new Exception("..." );

          //Do Something ....
          }
          }

          Yes, before we had to do a check for -1 or some other magic number, but i'd
          rather there was an up front way of saying - in this certain scope it may be
          nullable, but outside it must have a value before it can be used as a
          parameter and the above method defined as follows:

          public class MyBusiness
          {
          public void AttachToItem(in t id) //i now have a valid int !
          {
          if (!id.hasValue)
          throw new Exception("..." );

          //Do Something ....
          }
          }

          The only way i can think of solving this without writing loads of code,
          would be to have some kind of c#meta which allows you to put constraints on
          the variables in terms of scope, value, casting and exception.

          So I may define my nullable int? as follows (making all this up now):

          int? _id = null : valuecast(condi tion[value>0], IDException);


          This basically says, define my _id variable as a nullable int? and when it
          is cast to an int value - [ in order to solving having to check for nulls in
          all my methods and so allow then to be defined as proper int value types ] -
          if the current value of _id is not greater than 0 then throw the user
          defined IDException.

          Something like this would then provide me with a way of casting all of my
          fields for my entity throughout my entire application, which allows me to
          ensure that i do have a valid int (and it is NOT null) which is needed is
          almost all of my cases and my interfaces outside my entity can just use
          int's to define their interfaces.

          steven :: http://stevenR2.com


          Comment

          • Jay B. Harlow [MVP - Outlook]

            #6
            Re: Nullable types in a constructor?

            Steven,
            | public class MyBusiness
            | {
            | public void AttachToItem(in t? id)
            | {
            | if (!id.hasValue)
            | throw new Exception("..." );
            |
            | //Do Something ....
            | }
            | }
            You can simply use id.Value in "//Do Something ....", it will throw an
            exception for you if id.HasValue is false.

            For example:

            int? id = null;
            int value = id.Value;

            Will throw InvalidOperatio nException("Nul lable object must have a value")
            for you on the second line!

            Unfortunately it won't handle the id.Value > 0 trick.

            --
            Hope this helps
            Jay [MVP - Outlook]
            ..NET Application Architect, Enthusiast, & Evangelist
            T.S. Bradley - http://www.tsbradley.net


            "Steven Livingstone" <connect@NOSPAM .stevenR2.com> wrote in message
            news:%23fqKt7nI GHA.3020@TK2MSF TNGP10.phx.gbl. ..
            | This post started as a few lines and expanded to some off topic thoughts
            on
            | my frustrations with nullable value types - please comment if you wish
            and
            | i blogged it here :
            | http://stevenr2.blogspot.com/2006/01...rritation.html
            |
            | I have to say working with these things is a little irritating. Mainly
            | because you can't go implcitly from int? to int and so although in the
            | context of your Entity you may allow a null ID, the concept of a null ID
            may
            | NOT be something you wish to expose to method calls using the object or at
            | least avoid you having to type everything int? and then check hasValue.
            |
            | Here's is what I am talking about.
            |
            | You define a simple element entity as follows:
            |
            | public class Element
            | {
            | int? _id = null;
            |
            | public int? ID
            | {
            | get { return _id;}
            | set {_id=value;}
            | }
            | }
            |
            |
            | You then may have a data object as follows:
            |
            | public class MyData
            | {
            | public void Save(Element element)
            | {
            | if (element.ID == null)
            | SaveNew(...);
            | else
            | Update(...);
            | }
            | }
            |
            | The issue you now have is that any business methods, helper methods and so
            | on that use this ID can then expect two types of query. The first is where
            | you have a valid ID (number > 0) and the second is where you have a null
            | value. Therefore, everytime you want to call a method such as the
            following,
            | which will pass the ID of the element to the method you ALWAYS have to do
            | hasValue.
            |
            | public class MyBusiness
            | {
            | public void AttachToItem(in t? id)
            | {
            | if (!id.hasValue)
            | throw new Exception("..." );
            |
            | //Do Something ....
            | }
            | }
            |
            | Yes, before we had to do a check for -1 or some other magic number, but
            i'd
            | rather there was an up front way of saying - in this certain scope it may
            be
            | nullable, but outside it must have a value before it can be used as a
            | parameter and the above method defined as follows:
            |
            | public class MyBusiness
            | {
            | public void AttachToItem(in t id) //i now have a valid int !
            | {
            | if (!id.hasValue)
            | throw new Exception("..." );
            |
            | //Do Something ....
            | }
            | }
            |
            | The only way i can think of solving this without writing loads of code,
            | would be to have some kind of c#meta which allows you to put constraints
            on
            | the variables in terms of scope, value, casting and exception.
            |
            | So I may define my nullable int? as follows (making all this up now):
            |
            | int? _id = null : valuecast(condi tion[value>0], IDException);
            |
            |
            | This basically says, define my _id variable as a nullable int? and when it
            | is cast to an int value - [ in order to solving having to check for nulls
            in
            | all my methods and so allow then to be defined as proper int value
            types ] -
            | if the current value of _id is not greater than 0 then throw the user
            | defined IDException.
            |
            | Something like this would then provide me with a way of casting all of my
            | fields for my entity throughout my entire application, which allows me to
            | ensure that i do have a valid int (and it is NOT null) which is needed is
            | almost all of my cases and my interfaces outside my entity can just use
            | int's to define their interfaces.
            |
            | steven :: http://stevenR2.com
            |
            |


            Comment

            • Steven Livingstone

              #7
              Re: Nullable types in a constructor?

              Thanks Jay.

              I realized that, but it would be nice to tie some custom business logic to
              this exception as the casting isn't really an error in my case - rather an
              exception case when you have just initialized your entity.

              I guess it's just hard to support nulables and have valid values on the
              public interfaces to the object.

              steven :: http://stevenR2.com

              "Jay B. Harlow [MVP - Outlook]" <Jay_Harlow_MVP @tsbradley.net> wrote in
              message news:%23SSMIbqI GHA.3904@TK2MSF TNGP10.phx.gbl. ..[color=blue]
              > Steven,
              > | public class MyBusiness
              > | {
              > | public void AttachToItem(in t? id)
              > | {
              > | if (!id.hasValue)
              > | throw new Exception("..." );
              > |
              > | //Do Something ....
              > | }
              > | }
              > You can simply use id.Value in "//Do Something ....", it will throw an
              > exception for you if id.HasValue is false.
              >
              > For example:
              >
              > int? id = null;
              > int value = id.Value;
              >
              > Will throw InvalidOperatio nException("Nul lable object must have a value")
              > for you on the second line!
              >
              > Unfortunately it won't handle the id.Value > 0 trick.
              >
              > --
              > Hope this helps
              > Jay [MVP - Outlook]
              > .NET Application Architect, Enthusiast, & Evangelist
              > T.S. Bradley - http://www.tsbradley.net
              >
              >
              > "Steven Livingstone" <connect@NOSPAM .stevenR2.com> wrote in message
              > news:%23fqKt7nI GHA.3020@TK2MSF TNGP10.phx.gbl. ..
              > | This post started as a few lines and expanded to some off topic thoughts
              > on
              > | my frustrations with nullable value types - please comment if you wish
              > and
              > | i blogged it here :
              > |
              > http://stevenr2.blogspot.com/2006/01...rritation.html
              > |
              > | I have to say working with these things is a little irritating. Mainly
              > | because you can't go implcitly from int? to int and so although in the
              > | context of your Entity you may allow a null ID, the concept of a null ID
              > may
              > | NOT be something you wish to expose to method calls using the object or
              > at
              > | least avoid you having to type everything int? and then check hasValue.
              > |
              > | Here's is what I am talking about.
              > |
              > | You define a simple element entity as follows:
              > |
              > | public class Element
              > | {
              > | int? _id = null;
              > |
              > | public int? ID
              > | {
              > | get { return _id;}
              > | set {_id=value;}
              > | }
              > | }
              > |
              > |
              > | You then may have a data object as follows:
              > |
              > | public class MyData
              > | {
              > | public void Save(Element element)
              > | {
              > | if (element.ID == null)
              > | SaveNew(...);
              > | else
              > | Update(...);
              > | }
              > | }
              > |
              > | The issue you now have is that any business methods, helper methods and
              > so
              > | on that use this ID can then expect two types of query. The first is
              > where
              > | you have a valid ID (number > 0) and the second is where you have a null
              > | value. Therefore, everytime you want to call a method such as the
              > following,
              > | which will pass the ID of the element to the method you ALWAYS have to
              > do
              > | hasValue.
              > |
              > | public class MyBusiness
              > | {
              > | public void AttachToItem(in t? id)
              > | {
              > | if (!id.hasValue)
              > | throw new Exception("..." );
              > |
              > | //Do Something ....
              > | }
              > | }
              > |
              > | Yes, before we had to do a check for -1 or some other magic number, but
              > i'd
              > | rather there was an up front way of saying - in this certain scope it
              > may
              > be
              > | nullable, but outside it must have a value before it can be used as a
              > | parameter and the above method defined as follows:
              > |
              > | public class MyBusiness
              > | {
              > | public void AttachToItem(in t id) //i now have a valid int !
              > | {
              > | if (!id.hasValue)
              > | throw new Exception("..." );
              > |
              > | //Do Something ....
              > | }
              > | }
              > |
              > | The only way i can think of solving this without writing loads of code,
              > | would be to have some kind of c#meta which allows you to put constraints
              > on
              > | the variables in terms of scope, value, casting and exception.
              > |
              > | So I may define my nullable int? as follows (making all this up now):
              > |
              > | int? _id = null : valuecast(condi tion[value>0], IDException);
              > |
              > |
              > | This basically says, define my _id variable as a nullable int? and when
              > it
              > | is cast to an int value - [ in order to solving having to check for
              > nulls
              > in
              > | all my methods and so allow then to be defined as proper int value
              > types ] -
              > | if the current value of _id is not greater than 0 then throw the user
              > | defined IDException.
              > |
              > | Something like this would then provide me with a way of casting all of
              > my
              > | fields for my entity throughout my entire application, which allows me
              > to
              > | ensure that i do have a valid int (and it is NOT null) which is needed
              > is
              > | almost all of my cases and my interfaces outside my entity can just use
              > | int's to define their interfaces.
              > |
              > | steven :: http://stevenR2.com
              > |
              > |
              >
              >[/color]


              Comment

              Working...