Consider:
Language,
Framework,
Context.
1. Language
Using ∞ can be a solution for a maximum.
JavaScript, for example, has an infinity. C# doesn't¹.
Ada, for example, has ranges. C# doesn't.
In C#, there is int.MaxValue
, but you cannot use it in your case. int.MaxValue
is the maximum integer, 2,147,483,647. If in your code, you have a maximum value of something, like a maximum accepted pressure before something explodes, using 2,147,483,647 has no sense.
2. Framework
.NET Framework is rather inconsistent on this point, and its usage of magic values can be criticized.
For example, "Hello".IndexOf("Z")
returns a magic value -1
. It maybe makes it easier (does it?) to manipulate the result:
int position = "Hello".IndexOf("Z");
if (position > 0)
{
DoSomething(position);
}
rather than using a custom structure:
SearchOccurrence occurrence = "Hello".IndexOf("Z");
if (occurrence.IsFound)
{
DoSomething(occurrence.StartOffset);
}
but is not intuitive at all. Why -1
and not -123
? A beginner may also mistakenly think that 0
means "Not found" too or just mistype (position >= 0)
.
3. Context
If your code is related to timeouts in network sockets, using something which was used by everyone for decades for the sake of being consistent is not a bad idea. Especially, 0
for a timeout is very clear: it's a value which cannot be zero. Using a custom class in this case may make things more difficult to understand:
class Timeout
{
// A value indicating whether there is a timeout.
public bool IsTimeoutEnabled { get; set; }
// The duration of the timeout, in milliseconds.
public int Duration { get; set; }
}
- Can I set
Duration
to 0 if IsTimeoutEnabled
is true?
- If
IsTimeoutEnabled
is false, what happens if I set Duration
to 100?
This can lead to multiple mistakes. Imagine the following piece of code:
this.currentOperation.Timeout = new Timeout
{
// Set the timeout to 200 ms.; we don't want this operation to be longer than that.
Duration = 200,
};
this.currentOperation.Run();
The operation runs for ten seconds. Can you see what's wrong with this code, without reading the documentation of Timeout
class?
Conclusion
null
expresses well the idea that the value is not here. It's not provided. Not available. It's neither a number, nor a zero/empty string or whatsoever. Don't use it for maximum or minimum values.
int.MaxValue
is strongly related to the language itself. Don't use int.MaxValue
for a maximum speed limit of Vehicle
class or a maximum acceptable speed for an aircraft, etc.
Avoid magic values like -1
in your code. They are misleading and lead to mistakes in code.
Create your own class which would be more straightforward, with the minimum/maximum values specified. For example VehicleSpeed
can have VehicleSpeed.MaxValue
.
Don't follow any previous guideline and use magic values if it's a general convention for decades in a very specific field, used by most people writing code in this field.
Don't forget to mix approaches. For example:
class DnsQuery
{
public const int NoTimeout = 0;
public int Timeout { get; set; }
}
this.query.Timeout = 0; // For people who are familiar with timeouts set to zero.
// or
this.query.Timeout = DnsQuery.NoTimeout; // For other people.
¹ You can create your own type which includes infinity. Here, I'm talking about native int
type only.