Property validation logic in C Sharp (C#) - Time & Space Complexity
Start learning this pattern below
Jump into concepts and practice - no test required
When we check if a property value is valid, the time it takes depends on how many checks we do.
We want to know how the time grows when we add more validation rules or data.
Analyze the time complexity of the following code snippet.
public class User
{
private string _email;
public string Email
{
get => _email;
set
{
if (string.IsNullOrEmpty(value))
throw new ArgumentException("Email cannot be empty");
if (!value.Contains("@"))
throw new ArgumentException("Email must contain '@'");
_email = value;
}
}
}
This code checks two simple rules when setting the Email property: it must not be empty and must contain '@'.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Checking if the string contains '@' using the Contains method.
- How many times: This check scans the string characters once each time the property is set.
Explain the growth pattern intuitively.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 (characters) | About 10 checks to find '@' |
| 100 (characters) | About 100 checks |
| 1000 (characters) | About 1000 checks |
Pattern observation: The time to validate grows roughly in direct proportion to the length of the string.
Time Complexity: O(n)
This means the time to validate the property grows linearly with the length of the input string.
[X] Wrong: "Checking if a string contains a character is always instant, so time doesn't grow with input size."
[OK] Correct: The check looks at each character until it finds '@', so longer strings take more time.
Understanding how simple validation scales helps you write efficient code and explain your reasoning clearly in interviews.
"What if we added multiple validation rules that each scan the string? How would the time complexity change?"
Practice
Solution
Step 1: Understand property setters
Property setters allow you to assign values to private fields through a controlled interface.Step 2: Role of validation logic
Validation logic inside the setter checks if the value is valid before saving it, preventing invalid data.Final Answer:
To check and control the value before saving it to the field -> Option AQuick Check:
Validation in setter = control value before save [OK]
- Thinking validation makes property read-only
- Assuming validation speeds up code
- Confusing validation with default value assignment
Solution
Step 1: Identify correct exception throwing syntax
Throwing an exception uses the keyword 'throw' followed by 'new Exception(message)'.Step 2: Check each option
set { if (value < 0) throw new Exception("Invalid value"); field = value; } correctly throws an exception if value is less than zero. Others use invalid statements like return, Console.WriteLine, or break inside setter.Final Answer:
set { if (value < 0) throw new Exception("Invalid value"); field = value; } -> Option AQuick Check:
Throw exception = throw new Exception(...) [OK]
- Using 'return' instead of 'throw' in setter
- Trying to use 'break' inside setter
- Only printing error without stopping assignment
class Person {
private int age;
public int Age {
get => age;
set {
if (value < 0) throw new ArgumentException("Age cannot be negative");
age = value;
}
}
}
What happens if you run this code?
var p = new Person();
p.Age = -5;
Solution
Step 1: Analyze setter validation
The setter checks if value is less than 0 and throws ArgumentException if true.Step 2: Apply to given code
Setting Age to -5 triggers the exception because -5 < 0.Final Answer:
An ArgumentException is thrown with message 'Age cannot be negative' -> Option BQuick Check:
Negative age triggers ArgumentException [OK]
- Assuming negative value is accepted
- Confusing exception type thrown
- Thinking setter silently ignores invalid values
private string name;
public string Name {
get { return name; }
set {
if (value == null || value == "")
throw new ArgumentException("Name cannot be empty");
name = value;
}
}Solution
Step 1: Review validation logic
The setter checks if value is null or empty string but does not check if value is whitespace only.Step 2: Understand missing validation
Strings like " " (spaces) pass the check but are usually invalid for a name.Final Answer:
The setter does not check for whitespace-only strings -> Option CQuick Check:
Missing whitespace check in setter validation [OK]
- Thinking '==' is wrong for string comparison here
- Believing exceptions should never be thrown in setters
- Forgetting to assign value to field
Score that only accepts values between 0 and 100 inclusive. If the value is outside this range, it should throw an ArgumentOutOfRangeException. Which of these implementations correctly applies this validation?Solution
Step 1: Understand the range condition
The value must be between 0 and 100 inclusive, so invalid values are less than 0 or greater than 100.Step 2: Analyze each condition
private int score; public int Score { get => score; set { if (value < 0 || value > 100) throw new ArgumentOutOfRangeException("Score must be 0-100"); score = value; } } uses 'value < 0 || value > 100' which correctly checks invalid values. Options A, B, and D use incorrect logical operators or conditions.Final Answer:
private int score; public int Score { get => score; set { if (value < 0 || value > 100) throw new ArgumentOutOfRangeException("Score must be 0-100"); score = value; } } -> Option DQuick Check:
Use '||' for out-of-range checks [OK]
- Using '&&' instead of '||' in range checks
- Reversing comparison operators
- Throwing wrong exception type
