Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Ambiguous constructor signatures?

Ambiguous constructor signatures?

Scheduled Pinned Locked Moved C#
questionhelp
6 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    Clive D Pottinger
    wrote on last edited by
    #1

    Hello gurus and mavens! I haven't had to post any problems here in a while - which I take to be good sign for me. And this one isn't so much a "problem" as a "question". I thought the compiler would choke on the following code:

    namespace ConsoleApplication1
    {
    public class MyClass<G>
    {
    private G Val;

        public MyClass(string initStr)
        {
            if (initStr == "bad init string")
                throw new ApplicationException("You can't do that!");
            Val = default(G);
        }
    
        public MyClass(G initVal)
        {
            Val = initVal;
        }
    }
        
    class Program
    {
        static void Main(string\[\] args)
        {
            MyClass<int> example1 = new MyClass<int>("test"); // use the first constructor
            MyClass<int> example2 = new MyClass<int>(1);      // use the second constructor
    
            MyClass<string> example3 = new MyClass<string>("what happens here?"); // I want the second constructor
        }
    }
    

    }

    and tell me that it did not know which constructor to use with example3 since both constructors for MyClass would accept a string. But it didn't! Instead it just elects to use the constructor with the parameter of type string. Not what I expected, and not what I wanted. To get around this, I changed the second constructor to

    public MyClass(G initVal, bool dummy)

    and the call to

    MyClass<string> example3 = new MyClass<string>("what happens here?", true);

    just to make it clear that I want to use the second constructor. My question is this: is there a better way to handle this that I am not aware of? Is there some hidden option or obscure construct that makes sense of ambiguous constructor signatures? Many thanks,

    Clive Pottinger Victoria, BC

    D 1 Reply Last reply
    0
    • C Clive D Pottinger

      Hello gurus and mavens! I haven't had to post any problems here in a while - which I take to be good sign for me. And this one isn't so much a "problem" as a "question". I thought the compiler would choke on the following code:

      namespace ConsoleApplication1
      {
      public class MyClass<G>
      {
      private G Val;

          public MyClass(string initStr)
          {
              if (initStr == "bad init string")
                  throw new ApplicationException("You can't do that!");
              Val = default(G);
          }
      
          public MyClass(G initVal)
          {
              Val = initVal;
          }
      }
          
      class Program
      {
          static void Main(string\[\] args)
          {
              MyClass<int> example1 = new MyClass<int>("test"); // use the first constructor
              MyClass<int> example2 = new MyClass<int>(1);      // use the second constructor
      
              MyClass<string> example3 = new MyClass<string>("what happens here?"); // I want the second constructor
          }
      }
      

      }

      and tell me that it did not know which constructor to use with example3 since both constructors for MyClass would accept a string. But it didn't! Instead it just elects to use the constructor with the parameter of type string. Not what I expected, and not what I wanted. To get around this, I changed the second constructor to

      public MyClass(G initVal, bool dummy)

      and the call to

      MyClass<string> example3 = new MyClass<string>("what happens here?", true);

      just to make it clear that I want to use the second constructor. My question is this: is there a better way to handle this that I am not aware of? Is there some hidden option or obscure construct that makes sense of ambiguous constructor signatures? Many thanks,

      Clive Pottinger Victoria, BC

      D Offline
      D Offline
      DaveyM69
      wrote on last edited by
      #2

      This is expected behavior. MyClass(G) when G is a string becomes MyClass(string). As a constructor with those parameter types already exists a new one is not generated by the compiler as the parameter list must be different to successfully overload.

      Dave
      Generic BackgroundWorker - My latest article!
      BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
      Why are you using VB6? Do you hate yourself? (Christian Graus)

      K 1 Reply Last reply
      0
      • D DaveyM69

        This is expected behavior. MyClass(G) when G is a string becomes MyClass(string). As a constructor with those parameter types already exists a new one is not generated by the compiler as the parameter list must be different to successfully overload.

        Dave
        Generic BackgroundWorker - My latest article!
        BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
        Why are you using VB6? Do you hate yourself? (Christian Graus)

        K Offline
        K Offline
        Keith Barrow
        wrote on last edited by
        #3

        I'd go further and say this is the desired behaviour for the generic overload (i.e. I think the .Net framework makes the correct choice). MyClass(string foo) is explicitly stating "I deal with strings" and is therefore concrete, whereas MyClass(G foo) is stating "I deal with 'G's" which is less concrete. The design in the OP needs refactoring IMO, the concrete MyClass(string foo) ctor needs to be removed unless there is a specific reason for dealing with strings specifically. The validation performed on the strings is likely to be, but not necessarily, valid for other types.

        CCC solved so far: 2 (including a Hard One!)

        C 1 Reply Last reply
        0
        • K Keith Barrow

          I'd go further and say this is the desired behaviour for the generic overload (i.e. I think the .Net framework makes the correct choice). MyClass(string foo) is explicitly stating "I deal with strings" and is therefore concrete, whereas MyClass(G foo) is stating "I deal with 'G's" which is less concrete. The design in the OP needs refactoring IMO, the concrete MyClass(string foo) ctor needs to be removed unless there is a specific reason for dealing with strings specifically. The validation performed on the strings is likely to be, but not necessarily, valid for other types.

          CCC solved so far: 2 (including a Hard One!)

          C Offline
          C Offline
          Clive D Pottinger
          wrote on last edited by
          #4

          Thanks guys. That explains why it acts like it does.

          keefb wrote:

          The design in the OP needs refactoring [...] unless there is a specific reason for dealing with strings specifically.

          In the actual code MyClass is a class that represents some kind of value. The first ctor (MyClass(string initStr)) is used when the initStr holds a formula that needs to be parsed and evaluated to get the value. The second ctor (MyClass(G initVal, bool dummy)) is used when the value is already known, and does not need to be parsed or evaluated. The confusion arose, of course, when the value is a known string. I will take your recommendation to remove the first ctor into consideration, but at this point, I don't see a way for it work (is MyClass("foo()") a request for the string returned by foo or for the string "foo()"?). In the meantime, I will take it that my "workaround" is not wrong/dangerous/problematic/laughable. Thanks again.

          Clive Pottinger Victoria, BC

          K 1 Reply Last reply
          0
          • C Clive D Pottinger

            Thanks guys. That explains why it acts like it does.

            keefb wrote:

            The design in the OP needs refactoring [...] unless there is a specific reason for dealing with strings specifically.

            In the actual code MyClass is a class that represents some kind of value. The first ctor (MyClass(string initStr)) is used when the initStr holds a formula that needs to be parsed and evaluated to get the value. The second ctor (MyClass(G initVal, bool dummy)) is used when the value is already known, and does not need to be parsed or evaluated. The confusion arose, of course, when the value is a known string. I will take your recommendation to remove the first ctor into consideration, but at this point, I don't see a way for it work (is MyClass("foo()") a request for the string returned by foo or for the string "foo()"?). In the meantime, I will take it that my "workaround" is not wrong/dangerous/problematic/laughable. Thanks again.

            Clive Pottinger Victoria, BC

            K Offline
            K Offline
            Keith Barrow
            wrote on last edited by
            #5

            Clive D. Pottinger wrote:

            The first ctor (MyClass(string initStr)) is used when the initStr holds a formula that needs to be parsed and evaluated to get the value

            This is a worry*, and the source of your problem. If possible, you should defer the instantiation of this class until you have the value you want to use. If I understand you correctly, by passing the formula as a string will require the current class to be responsible for performing the parsing as well as whatever this class is meant to do with the result, this is probably bad object encapsulation. A better way to handle this is to create an object which is responsible for the storage and parsing of the formula, and pass the results of the formula into the current class ,explained in your original post. This will separate the concerns more clearly. * This is a worry because, unless you are parsing text entries from a user or some other source (e.g. text input from a UI or file), writing formulas in strings and then evaluating them is bad design (and a real pain. If this is the case, then it's unavoidable. If you are just using this to pass formulae around within the application, you should look at c# delegates(which allow you to pass methods around as parameters) and possibly the strategy pattern. Hope this helps!

            CCC solved so far: 2 (including a Hard One!)

            C 1 Reply Last reply
            0
            • K Keith Barrow

              Clive D. Pottinger wrote:

              The first ctor (MyClass(string initStr)) is used when the initStr holds a formula that needs to be parsed and evaluated to get the value

              This is a worry*, and the source of your problem. If possible, you should defer the instantiation of this class until you have the value you want to use. If I understand you correctly, by passing the formula as a string will require the current class to be responsible for performing the parsing as well as whatever this class is meant to do with the result, this is probably bad object encapsulation. A better way to handle this is to create an object which is responsible for the storage and parsing of the formula, and pass the results of the formula into the current class ,explained in your original post. This will separate the concerns more clearly. * This is a worry because, unless you are parsing text entries from a user or some other source (e.g. text input from a UI or file), writing formulas in strings and then evaluating them is bad design (and a real pain. If this is the case, then it's unavoidable. If you are just using this to pass formulae around within the application, you should look at c# delegates(which allow you to pass methods around as parameters) and possibly the strategy pattern. Hope this helps!

              CCC solved so far: 2 (including a Hard One!)

              C Offline
              C Offline
              Clive D Pottinger
              wrote on last edited by
              #6

              Thanks for the clarification, keefb.

              keefb wrote:

              If I understand you correctly, by passing the formula as a string will require the current class to be responsible for performing the parsing as well as whatever this class is meant to do with the result, this is probably bad object encapsulation.

              Agreed. But the class is not actually responsible for the parsing or evaluation (it passes those tasks off to another class), nor is it responsible for acting on the value. The class just holds on to expression tree created by parsing the formula and uses it to provide a value when requested. Perhaps my original example was over-simplified.

              keefb wrote:

              ...unless you are parsing text entries from a user or some other source (e.g. text input from a UI or file), writing formulas in strings and then evaluating them is bad design...

              This is exactly what I am doing. The formulas are read from user-created XML files and used to control the program's behaviour. This is fun... every criticism you offer just seems to confirm that I'm doing it correctly :laugh: . Keep going, keefb... one more critique should cement that I'm the bona fide genuis that I always knew myself to be:cool: (no matter what those jerks at Mensa had to say :mad:)

              Clive Pottinger Victoria, BC

              1 Reply Last reply
              0
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


              • Login

              • Don't have an account? Register

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • World
              • Users
              • Groups