Can I specify a default Color parameter in C# 4.0?
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.
}
Related videos on Youtube
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, 2020Comments
-
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 theColor.Black
value. -
Vlad over 13 yearswhy not just
if (boxColor == default(Color))
? -
George Johnston over 13 yearsI had that in my answer, but if you're going to specify a null argument, why not just specify Color.Black? :)
-
Vlad over 13 years@George: "Color.Black is a static, not a constant".
-
Mike Webb over 13 yearsThe 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 over 13 yearsIt doesn't make a difference. I prefer the Equals notation, but with value types, the '==' is identical.
-
Brian Ball over 13 yearsColor 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 over 13 yearsIndeed, you are explicitly referencing
Color?
, taking my comment back. -
Vlad over 13 years@Mr. TA: well, in this case it could be better to use
Color.Equals
instead ofobject.Equals
. Or betterdefault(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 over 13 yearsMaybe 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 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 over 13 years@Mr. TA: (1) Color.Equals is virtual, see msdn.microsoft.com/en-us/library/e03x8ct2.aspx. (2)
default(Color)
is nevernull
. (3)Color.Equals
is better thanobject.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 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 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 asobject.Equals
. -
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 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 almost 6 yearsI 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...