Can I specify a default Color parameter in C# 4.0?

14,822

Solution 1

Color.Black is a static, not a constant, so no, you cannot do this.

To use a default, you can make the parameter nullable (Color?), and if it is null, then set it to Black.

Solution 2

Do this:

void foo(... Color boxColor = default(Color))
{
   if(object.Equals(boxColor, default(Color))) boxColor = Color.Black;

  // ...
}

Quick aside: I like to use object.Equals static method because it's a consistent way to write an equality comparison. With reference types such as string, str.Equals("abc") can throw NRE, whereas string.Equals(str, "abc"[,StringComparison.___]) will not. Color is a value type and therefore will never be null, but it's better to be consistent in code style, especially at zero additional cost. Obviously this doesn't apply to primitives such as int and even DateTime, where == clearly states/communicates the mathematical equality comparison.

Or, with nullables (credit to Brian Ball's answer):

void foo(... Color? boxColor = null)
{
   if(boxColor == null) boxColor = Color.Black;

  // ...
}

Solution 3

What's wrong with keeping it simple?

public void DrawSquare(int x, int y)
{
    DrawSquare(x,y,Color.Black);
}

public void DrawSquare(int x, int y, Color color)
{
   // Do your thing.
}
Share:
14,822

Related videos on Youtube

Mike Webb
Author by

Mike Webb

I am a full time software developer working for BizStream. I love what I do and am always excited for new and interesting projects. I love my wife, my kids, my life, helping and hanging out with others, and working for Jesus Christ as He has called me.

Updated on December 29, 2020

Comments

  • Mike Webb
    Mike Webb over 3 years

    Here is an example function:

    public void DrawSquare(int x, int y, Color boxColor = Color.Black)
    {
        //Code to draw the square goes here 
    }
    

    The compiler keeps giving me the error: Default parameter value for 'boxColor'must be a compile-time constant

    I have tried

    Color.Black, 
    Color.FromKnownColor(KnownColor.Black), and 
    Color.FromArgb(0, 0, 0)
    

    How do I make Color.Black be the default color? Also, I do not want to use a string Black to specify it (which I know would work). I want the Color.Black value.

  • Vlad
    Vlad over 13 years
    why not just if (boxColor == default(Color))?
  • George Johnston
    George Johnston over 13 years
    I had that in my answer, but if you're going to specify a null argument, why not just specify Color.Black? :)
  • Vlad
    Vlad over 13 years
    @George: "Color.Black is a static, not a constant".
  • Mike Webb
    Mike Webb over 13 years
    The actual function is not that simple. It has around 10 parameters (most of which are optional and can be specified as optional). Plus there are 5 or 6 different functions with these parameters and two variations of each function. To do the above would add way too many functions. Thank you for the suggestion, though.
  • Mr. TA
    Mr. TA over 13 years
    It doesn't make a difference. I prefer the Equals notation, but with value types, the '==' is identical.
  • Brian Ball
    Brian Ball over 13 years
    Color is a struct, so if you were to use Nullable<Color> as the type (or in C# Color? for short), then it can be null.
  • Vlad
    Vlad over 13 years
    Indeed, you are explicitly referencing Color?, taking my comment back.
  • Vlad
    Vlad over 13 years
    @Mr. TA: well, in this case it could be better to use Color.Equals instead of object.Equals. Or better default(Color).Equals(boxColor) so that you use the virtual function. In my opinion, == is more readable, but it's a question of personal taste.
  • CallMeLaNN
    CallMeLaNN over 13 years
    Maybe it is a performance nad how the algorithm to check for equality, If I not mistaken, I notice the someString == "abc" is not same as someString.Equal("abc") in performance, best practise to use Equal(). Color is value type which mostly == and Equal() produce the same, but for reference type (except string), == and Equal() give much different meaning, == for check the reference equal while the Equal() is depend on the type if the Equal() method overridden.
  • Mr. TA
    Mr. TA over 13 years
    @Vlad: there are no virtual functions in value types, and Color.Equals is the same as object.Equals, same as default(Color).Equals(boxColor). The only benefit, IMO, of using object.Equals or Color.Equals over default(Color).Equals(boxColor) is that you are underscoring the fact that you're comparing two values, much in the same way "==" is written - it's a readability issue. Also, for consistency sake, object.Equals(x,y) is better than x.Equals(y) because with reference types, x.Equals(y) can throw NRE, whereas with object.Equals(x,y) you're safe.
  • Vlad
    Vlad over 13 years
    @Mr. TA: (1) Color.Equals is virtual, see msdn.microsoft.com/en-us/library/e03x8ct2.aspx. (2) default(Color) is never null. (3) Color.Equals is better than object.Equals, because the latter can only compare the references (however, it can do the right thing for the value types). More on the topic: blogs.msdn.com/b/ericlippert/archive/2009/04/09/…
  • Mr. TA
    Mr. TA over 13 years
    @Vlad: (1) It's not really virtual, because there's no v-table on a value-type. Secondly, there's no benefit of using object.Equals(x,y) over x.Equals(y) with regards to Equals being virtual or not in the first place. (2) I was referring to code readability and consistency; I said that for reference types, that could be a problem, and hence it's easier to stick to a rule to always use object.Equals(x,y). (3) There's absolutely no difference between object.Equals(x,y) and Color.Equals(x,y), they are one and the same. The links are actually irrelevant to our discussion, but thanks anyways.
  • Vlad
    Vlad over 13 years
    @Mr. TA: (1) in which meaning "not really virtual"? The observable behaviour is that instead of Object.Equals the specific Color.Equals is called. Whether there is or is no vtable is an implementation detail. The behaviour is as of a virtual function, the declaration is as of virtual function, so the function is virtual. You can look up the function Color.Equals in Reflector to ensure that does not exactly the same thing as object.Equals.
  • Vlad
    Vlad over 13 years
    @Mr. TA: (3) There is a difference, you can check it yourself. The code in Color.Equals looks like this: public override bool Equals(object obj) { if (obj is Color) { Color color = (Color) obj; if (((this.value == color.value) && (this.state == color.state)) && (this.knownColor == color.knownColor)) { return ((this.name == color.name) || (((this.name != null) && (color.name != null)) && this.name.Equals(this.name))); } } return false; }
  • Mr. TA
    Mr. TA over 13 years
    @Vlad: (1) That is correct. But it doesn't change the fact that the correct method is called regardless of calling object.Equals(color1, color2) or color1.Equals(color2). (3) I was referring to the static methods object.Equals(x,y) and Color.Equals(x,y), and you're describing the instance methods object.Equals(y) and Color.Equals(y). My original point was that using the static method object.Equals(x,y) is the best approach across the board, for value types and reference types alike.
  • Will Croxford
    Will Croxford almost 6 years
    I think @Vlad looks more readable so +1'd as someone else will understand it quickest, and while the virtual function discussion over my head as relative beginner still, I'm assuming any performance saving would not be such big thing...