Tech Off Thread

21 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

Optional parameters are evil

Back to Forum: Tech Off
  • User profile image
    vesuvius

    For me, I am finding that they are creating more problems than they solve. Yesterday I spent a substantial amount of time finding that famous bug where;

     

    enum SomeEnum{One, Two};

    SomeClass

    {

    private SomeEnum someEnum;

     

    private DoWork(SomeEnum? someEnum = null)

    {

    someEnum = someEnum;

    }

     

     

    now I could have prevented the bug by using _someEnum when declaring the enumeration, but I did not write the class. It is this coupled with Phil's versioning issue that have made me decide against them. I know they save keystrokes but don't save on headaches.

  • User profile image
    Dexter

    I don't see how this relates to optional parameters, if you remove the optional parameter the problem remains. Unless your real code is different than your example (which doesn't compile anyway).

     

  • User profile image
    Sven Groot

    Why is this symptomatic of optional parameters? I can run into exactly the same problem without them:

     

    enum SomeEnum{One, Two};
    class SomeClass
    {
      private SomeEnum someEnum;
    
      private DoWork(SomeEnum someEnum)
      {
        someEnum = someEnum;
      }
    }

     

    No optional parameters, same problem.

  • User profile image
    AndyC

    Sven Groot said:

    Why is this symptomatic of optional parameters? I can run into exactly the same problem without them:

     

    enum SomeEnum{One, Two};
    class SomeClass
    {
      private SomeEnum someEnum;
    
      private DoWork(SomeEnum someEnum)
      {
        someEnum = someEnum;
      }
    }

     

    No optional parameters, same problem.

    Naming variables and types the same but differing only by case has always been a bad idea. To be honest, it's one of the better features of VB that case insensitivity stops you doing something that daft in the first place.

     

    And that versioning "problem" is a deeply flawed argument anyway, for an API consumed by external callers all you need do is add a new overload without an optional parameter. Which is exactly what you'd have to do if optional parameters weren't allowed in the first place, since optional parameters are really just a tidy way of doing complex overloads.

  • User profile image
    Sven Groot

    AndyC said:
    Sven Groot said:
    *snip*

    Naming variables and types the same but differing only by case has always been a bad idea. To be honest, it's one of the better features of VB that case insensitivity stops you doing something that daft in the first place.

     

    And that versioning "problem" is a deeply flawed argument anyway, for an API consumed by external callers all you need do is add a new overload without an optional parameter. Which is exactly what you'd have to do if optional parameters weren't allowed in the first place, since optional parameters are really just a tidy way of doing complex overloads.

    it's one of the better features of VB that case insensitivity stops you doing something that daft in the first place

    That's not true, "Dim someClass as SomeClass" is perfectly valid VB. As is "Dim SomeClass As SomeClass". And for that matter, so's "SomeClass SomeClass;" in C#. The compiler is smart enough to figure out when you mean the type and when you mean the variable.

  • User profile image
    W3bbo

    Sven Groot said:
    AndyC said:
    *snip*

    That's not true, "Dim someClass as SomeClass" is perfectly valid VB. As is "Dim SomeClass As SomeClass". And for that matter, so's "SomeClass SomeClass;" in C#. The compiler is smart enough to figure out when you mean the type and when you mean the variable.

    It's especially a problem when writing classes which contain properties whose names matches types.

     

    It's a contrived example, but consider:

     

    enum Type { Person, Animal, Chimera }

     

    class Thing {

     

    public Type Type { get; private set; }

     

    }

     

  • User profile image
    Dr Herbie

    You're not doing constraint checking?  Tongue Out

     

    Herbie

  • User profile image
    exoteric

    I prefix locals with this. in constructors. The anti-pattern you use here should be caught by static analysis. One thing catches my eye and that is the fact that you just accept a null value instead of an actual enumeration value.

     

    Now about the criticism of optional parameters, well, one one hand, it's like saying a shovel is evil - in the hands of a homicidal maniac it can be used for evil, sure, but it's just a tool, you can use it well and you can use it poorly. A separate question is whether there exist other tools that solve the same problem but don't have the same perceived issues. No idea...

  • User profile image
    W3bbo

    exoteric said:

    I prefix locals with this. in constructors. The anti-pattern you use here should be caught by static analysis. One thing catches my eye and that is the fact that you just accept a null value instead of an actual enumeration value.

     

    Now about the criticism of optional parameters, well, one one hand, it's like saying a shovel is evil - in the hands of a homicidal maniac it can be used for evil, sure, but it's just a tool, you can use it well and you can use it poorly. A separate question is whether there exist other tools that solve the same problem but don't have the same perceived issues. No idea...

    This is why I preferred how things were done in C# 1.0: you could call methods with optional arguments, but not define them yourself (after all, you're far more likely to consume COM in .NET rather than write COM servers). I don't buy the arguments they made for introducing it in C# 4.0. If people really needed it then they should have used attributes and so kept the core language clean.

  • User profile image
    exoteric

    W3bbo said:
    exoteric said:
    *snip*

    This is why I preferred how things were done in C# 1.0: you could call methods with optional arguments, but not define them yourself (after all, you're far more likely to consume COM in .NET rather than write COM servers). I don't buy the arguments they made for introducing it in C# 4.0. If people really needed it then they should have used attributes and so kept the core language clean.

    Is the language really "polluted" by optional parameters? I don't see it. Besides, this was requested by many people. The endless overloads with one more parameters just went away in a flash.

     

    Say C# were to be refactored to something like D# then optional parameters would not be on my list of things to dispense of.

     

    It would be to streamline the language for immutability, genericity, non-nullness, numerics and in-memory query performance (read: LINQ to Objects).

     

    Wouldn't it be cool if nullness was dealt with by the maybe monad and we could just chain together nullable expressions without worrying about run-time blowups; if perhaps exceptions by the error monad - with some syntactic support; if = meant equality and := (or <-) meant assignment; if "assigning" to a structure didn't change it but constructed a functional variation of the old one, using techniques from persistent data structures (or the state monad?)

     

    Then there's the tension between interfaces, abstract classes, partial classes and extensions; many ways to skin a cat, none entirely general or generic.

     

    I'm getting close to biting the F# bullet, except there's no Visual F# Express, and I'd most likely only be using this at home for hobby projects, for the next couple of years.

  • User profile image
    AndyC

    W3bbo said:
    exoteric said:
    *snip*

    This is why I preferred how things were done in C# 1.0: you could call methods with optional arguments, but not define them yourself (after all, you're far more likely to consume COM in .NET rather than write COM servers). I don't buy the arguments they made for introducing it in C# 4.0. If people really needed it then they should have used attributes and so kept the core language clean.

    You could call them in C#1.0, but if you ever tried Office Automation you'd discover very quickly that it was hideous beyond belief as soon as there were more than a couple of optional arguments. A lot of COM interfaces (the Office suite object models being the prime example) pretty much depend entirely on the availability of both named and optional parameters if they are to be usable at all. I think more people are seeing problems with optional arguments than actually exist in reality.

  • User profile image
    spivonious

    This is why I always prefix my instance-level variables with "m".

     

    With that said, it would be helpful if the compiler at least gave a warning about this. When would you ever want to set a variable to itself?

  • User profile image
    Dexter

    spivonious said:

    This is why I always prefix my instance-level variables with "m".

     

    With that said, it would be helpful if the compiler at least gave a warning about this. When would you ever want to set a variable to itself?

    But it does give a warning. Compiling the original example gives something like this:

     

    Program.cs(31,13): warning CS1717: Assignment made to same variable; did you mean to assign something else?

  • User profile image
    PerfectPhase

    W3bbo said:
    exoteric said:
    *snip*

    This is why I preferred how things were done in C# 1.0: you could call methods with optional arguments, but not define them yourself (after all, you're far more likely to consume COM in .NET rather than write COM servers). I don't buy the arguments they made for introducing it in C# 4.0. If people really needed it then they should have used attributes and so kept the core language clean.

    I think some of it comes down to the fact the people writing the PIAs for COM objects want to use C#, so need optional parameters to make it useable for us.

  • User profile image
    exoteric

    PerfectPhase said:
    W3bbo said:
    *snip*

    I think some of it comes down to the fact the people writing the PIAs for COM objects want to use C#, so need optional parameters to make it useable for us.

    I've used optional parameters many times but not a single time for a COM interop scenario. Really, they're more than a COM helper. There may be better ways of skinning this cat* but they sure do allow you to shorten your code and turn it into something I think is quite readable and understandable.

     

    The whole business of programming is about doing more with less, be it helping people be more productive (via applications) or other programs (via libraries and frameworks) or all programs (via programming languages). Do as much as possible with as little effort as possible, whilst not sacrificing quality, robustness, safety, efficiency, composability, etc.

     

    * I wonder if there are ways to express this nicely in functional programming languages.

  • User profile image
    Shining Arcanine

    Sven Groot said:

    Why is this symptomatic of optional parameters? I can run into exactly the same problem without them:

     

    enum SomeEnum{One, Two};
    class SomeClass
    {
      private SomeEnum someEnum;
    
      private DoWork(SomeEnum someEnum)
      {
        someEnum = someEnum;
      }
    }

     

    No optional parameters, same problem.

    enum SomeEnum{One, Two}; class SomeClass { private SomeEnum someEnum; private DoWork(SomeEnum someEnum) { this->someEnum = someEnum; } }

     

    That should fix it. Although I have never tried it, ::someEnum or SomeClass::someEnum might also work.

  • User profile image
    exoteric

    Shining Arcanine said:
    Sven Groot said:
    *snip*

    enum SomeEnum{One, Two}; class SomeClass { private SomeEnum someEnum; private DoWork(SomeEnum someEnum) { this->someEnum = someEnum; } }

     

    That should fix it. Although I have never tried it, ::someEnum or SomeClass::someEnum might also work.

    Aside from the fact that the code does not fix it (not valid C#), I'm pretty sure Sven is aware of the solution to this problem. Wink

  • User profile image
    Shining Arcanine

    exoteric said:
    Shining Arcanine said:
    *snip*

    Aside from the fact that the code does not fix it (not valid C#), I'm pretty sure Sven is aware of the solution to this problem. Wink

    I have been around so much Java that I am beginning to mix and match Java and C++. In my mind, that was valid C++ code. Sad

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.