An indexer allows an object to be indexed like an array, using the square bracket syntax []. It lets you access elements inside a class or struct using a key or index.
Click to reveal answer
intermediate
Can indexers use custom types as their index parameter?
Yes, indexers can use any type as the index parameter, including custom classes or structs, as long as the type supports equality comparison if needed.
Click to reveal answer
intermediate
How do you declare an indexer with a custom type as the index in C#?
You declare the indexer with the custom type inside the square brackets. For example: public string this[MyKey key] { get { ... } set { ... } }
Click to reveal answer
intermediate
Why might you use a custom type as an indexer key instead of a simple type like int or string?
Using a custom type allows you to use complex keys that group multiple values or have special behavior, making your code clearer and more organized.
Click to reveal answer
advanced
What must a custom type used as an indexer key implement or override for correct behavior?
It should override Equals() and GetHashCode() methods to ensure correct comparison and hashing, especially if used in collections like dictionaries internally.
Click to reveal answer
Which of the following can be used as an index parameter in a C# indexer?
AOnly int and string types
BAny type, including custom classes or structs
COnly primitive types like int, double, bool
DOnly types that implement IEnumerable
✗ Incorrect
C# indexers can use any type as the index parameter, including custom types.
What keyword is used to declare an indexer in a C# class?
Aindex
Bget
Cset
Dthis
✗ Incorrect
The keyword 'this' is used to declare an indexer in C#.
If you use a custom type as an indexer key, what should you override for correct key comparison?
AToString()
BCompareTo()
CEquals() and GetHashCode()
DFinalize()
✗ Incorrect
Overriding Equals() and GetHashCode() ensures correct comparison and hashing of keys.
What is the return type of an indexer in C#?
AAny type defined by the indexer
BAlways int
CAlways string
Dvoid
✗ Incorrect
The return type of an indexer can be any type you define.
Which of these is a valid indexer declaration using a custom type 'Key'?
Apublic string this[Key key] { get; set; }
Bpublic void this[Key key] { get; set; }
Cpublic Key this[string index] { get; set; }
Dpublic int this[int index] { get; set; }
✗ Incorrect
An indexer must have a return type other than void; option A is valid with a custom type as index.
Explain how to create an indexer in C# that uses a custom class as the index parameter.
Think about how you access elements like an array but with your own key type.
You got /4 concepts.
Why is it important to override Equals() and GetHashCode() in a custom type used as an indexer key?
Consider what happens when you look up keys in a dictionary.
You got /3 concepts.
Practice
(1/5)
1.
What is the main purpose of an indexer in a C# class?
Choose the best description.
easy
A. To create a constructor for initializing objects.
B. To define a method that returns the size of a collection.
C. To allow objects to be accessed using array-like bracket syntax with custom keys.
D. To overload the + operator for custom types.
Solution
Step 1: Understand what an indexer does
An indexer lets you use square brackets [] to access elements inside an object, similar to arrays.
Step 2: Identify the correct description
Only To allow objects to be accessed using array-like bracket syntax with custom keys. describes this behavior correctly by mentioning bracket syntax and custom keys.
Final Answer:
To allow objects to be accessed using array-like bracket syntax with custom keys. -> Option C
Quick Check:
Indexer = bracket access [OK]
Hint: Indexers let you use [] on objects like arrays [OK]
Common Mistakes:
Confusing indexers with constructors
Thinking indexers define collection size
Mixing indexers with operator overloading
2.
Which of the following is the correct syntax to declare an indexer in a C# class using a custom type Key as the index?
public class MyCollection {
// Indexer declaration here
}
easy
A. public string this[Key key] { get; set; }
B. public string this(Key key) { get; set; }
C. public string this[Key] { get; set; }
D. public string this[Key key] => get; set;
Solution
Step 1: Recall indexer syntax
Indexers use the keyword this followed by square brackets with the parameter type and name inside.
Step 2: Check each option
public string this[Key key] { get; set; } correctly uses this[Key key] with get and set accessors. Others have syntax errors or wrong brackets.
Final Answer:
public string this[Key key] { get; set; } -> Option A
Hint: Indexer uses this[Type name] with get/set inside braces [OK]
Common Mistakes:
Using parentheses instead of brackets
Omitting parameter name in brackets
Using expression-bodied syntax incorrectly
3.
Given the following code, what will be the output?
public record Key(int Id);
public class Store {
private Dictionary<Key, string> data = new();
public string this[Key key] {
get => data.TryGetValue(key, out var val) ? val : "Not found";
set => data[key] = value;
}
}
var store = new Store();
store[new Key(1)] = "Apple";
store[new Key(2)] = "Banana";
Console.WriteLine(store[new Key(1)]);
Console.WriteLine(store[new Key(3)]);
medium
A. Not found\nNot found
B. Apple\nBanana
C. Compilation error
D. Apple\nNot found
Solution
Step 1: Understand how the indexer accesses data
The indexer uses a Dictionary with Key as key type. It returns the value if found, else "Not found".
Step 2: Check the keys used
Keys with Id 1 and 2 are added. Accessing new Key(1) finds "Apple". Accessing new Key(3) is missing, so returns "Not found".
Final Answer:
Apple
Not found -> Option D
Quick Check:
Key(1) found, Key(3) missing = Apple, Not found [OK]
Assuming new Key(1) is different from stored Key(1)
Expecting Banana for Key(3)
Ignoring TryGetValue fallback
4.
Identify the error in the following code snippet that implements an indexer with a custom type Key:
public class DataStore {
private Dictionary<Key, int> dict = new();
public int this[Key key] {
get { return dict[key]; }
set { dict.Add(key, value); }
}
}
medium
A. Using dict.Add in set causes exception if key exists; should use dict[key] = value.
B. Indexer must return string, not int.
C. Key type cannot be used as indexer parameter.
D. Missing constructor for DataStore class.
Solution
Step 1: Analyze the set accessor
The set accessor uses dict.Add(key, value), which throws an exception if the key already exists.
Step 2: Suggest correct usage
To update or add, use dict[key] = value; which overwrites existing or adds new key.
Final Answer:
Using dict.Add in set causes exception if key exists; should use dict[key] = value. -> Option A
Quick Check:
dict.Add throws if key exists; use dict[key] = value [OK]
Hint: Use dict[key] = value to avoid exceptions on set [OK]
Common Mistakes:
Using Add instead of index assignment in set
Thinking Key cannot be indexer parameter
Confusing return types in indexer
5.
You want to create a class Matrix that uses a custom struct Position as the indexer key to store integer values. The Position struct has two int fields: Row and Col. Which approach correctly implements the indexer to allow getting and setting values by Position?
public struct Position {
public int Row, Col;
public Position(int r, int c) { Row = r; Col = c; }
}
public class Matrix {
private Dictionary<Position, int> values = new();
// Implement indexer here
}
hard
A. public int this[Position pos] { get => values[pos]; set => values[pos] = value; }
B. public int this[Position pos] { get => values.TryGetValue(pos, out var v) ? v : 0; set => values[pos] = value; }
C. public int this[Position pos] { get { return values[pos]; } set { values.Add(pos, value); } }
D. public int this[int row, int col] { get => values[new Position(row, col)]; set => values[new Position(row, col)] = value; }
Solution
Step 1: Consider safe get behavior
Using TryGetValue with fallback 0 avoids exceptions if the position key is missing.
Step 2: Check set accessor correctness
Using values[pos] = value; safely adds or updates the dictionary entry.
Step 3: Evaluate other options
public int this[int row, int col] { get => values[new Position(row, col)]; set => values[new Position(row, col)] = value; } uses two parameters, not matching the question's single Position key. public int this[Position pos] { get { return values[pos]; } set { values.Add(pos, value); } } uses Add in set, which throws if key exists. public int this[Position pos] { get => values[pos]; set => values[pos] = value; }'s get accessor throws if key missing.
Final Answer:
public int this[Position pos] { get => values.TryGetValue(pos, out var v) ? v : 0; set => values[pos] = value; } -> Option B
Quick Check:
Safe get with TryGetValue + index assignment set [OK]
Hint: Use TryGetValue in get to avoid exceptions on missing keys [OK]
Common Mistakes:
Using Add in set causing exceptions
Not handling missing keys in get
Using multiple parameters instead of custom type
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.