📖 Scenario: You work in a store that sells different products. You want to keep a list of products and filter them based on their price.
🎯 Goal: Create a generic class that can filter products by price using a generic constraint with a where clause.
📋 What You'll Learn
Create a class Product with properties Name (string) and Price (decimal).
Create a generic class Filter<T> with a where clause that restricts T to be Product or a subclass.
Add a method FilterByPrice in Filter<T> that returns products with price less than a given value.
Create a list of Product objects with exact values.
Use the FilterByPrice method to get products cheaper than a specific price and print their names.
💡 Why This Matters
🌍 Real World
Stores and e-commerce platforms often filter products by price or other attributes. Using generic constraints helps create reusable filtering classes.
💼 Career
Understanding generic constraints and filtering data is important for software developers working with collections, databases, and APIs.
Progress0 / 4 steps
1
Create the Product class and product list
Create a class called Product with two public properties: Name of type string and Price of type decimal. Then create a list called products with these exact entries: new Product { Name = "Pen", Price = 1.5m }, new Product { Name = "Notebook", Price = 3.0m }, new Product { Name = "Backpack", Price = 25.0m }.
C Sharp (C#)
Hint
Define the Product class with two properties. Then create a List<Product> with the exact products.
2
Add generic Filter class with where constraint
Create a generic class called Filter<T> with a where clause that restricts T to be Product or a subclass. Inside it, add a public field items of type List<T>.
C Sharp (C#)
Hint
Use where T : Product to restrict the generic type. Add a constructor to set the items field.
3
Add FilterByPrice method to Filter class
Inside the Filter<T> class, add a method called FilterByPrice that takes a decimal maxPrice parameter and returns a List<T> of items with Price less than maxPrice. Use LINQ Where to filter.
C Sharp (C#)
Hint
Use LINQ Where to select items with price less than maxPrice.
4
Use Filter class and print filtered product names
In the Main method, create an instance of Filter<Product> called filter using the products list. Then call FilterByPrice with 5.0m and store the result in cheapProducts. Finally, print the Name of each product in cheapProducts on separate lines.
C Sharp (C#)
Hint
Create the Filter<Product> instance and call FilterByPrice(5.0m). Print each product's Name from the result.
Practice
(1/5)
1. What is the purpose of the where clause in C# generic constraints?
easy
A. To limit the types that can be used with a generic type parameter
B. To define a new generic type
C. To create a database connection string
D. To specify the return type of a method
Solution
Step 1: Understand generic constraints
The where clause restricts which types can be used with a generic type parameter.
Step 2: Identify the purpose of the where clause
It ensures only types meeting certain conditions (like implementing an interface) are allowed.
Final Answer:
To limit the types that can be used with a generic type parameter -> Option A
Quick Check:
Generic constraints = limit types [OK]
Hint: Think of where as a filter for allowed types [OK]
Common Mistakes:
Confusing where with method return types
Thinking where defines new types
Using where for database queries
2. Which of the following is the correct syntax to constrain a generic type T to be a class in C#?
easy
A. where T : new()
B. where T : struct
C. where T : class
D. where T : interface
Solution
Step 1: Recall constraint keywords
class means the type must be a reference type (class).
Step 2: Match syntax to constraint
where T : class correctly restricts T to reference types.
Final Answer:
where T : class -> Option C
Quick Check:
Class constraint uses class keyword [OK]
Hint: Remember: class means reference type, struct means value type [OK]
Common Mistakes:
Using struct to mean class
Confusing new() with class constraint
Writing interface as a constraint keyword
3. Consider this code snippet:
class Repository<T> where T : IEntity { public void Save(T item) { item.Save(); } } interface IEntity { void Save(); }
What will happen if you try to create Repository<string>?
medium
A. Compile-time error because string does not implement IEntity
B. Runs successfully and calls string.Save()
C. Compile-time error because string is a value type
D. Runs successfully but does nothing
Solution
Step 1: Check the constraint on T
T must implement IEntity.
Step 2: Verify if string implements IEntity
string does not implement IEntity, so it violates the constraint.
Final Answer:
Compile-time error because string does not implement IEntity -> Option A
Quick Check:
Constraint violation = compile error [OK]
Hint: Check if type meets interface constraint before using [OK]
4. Identify the error in this generic class declaration:
class DataManager<T> where T : new, class { }
medium
A. The new constraint should be new() with parentheses
B. The order of constraints is incorrect; class must come before new()
C. There is no error; this is valid syntax
D. The class constraint cannot be combined with new()
Solution
Step 1: Recall correct order of constraints
In C#, class or struct constraints must come before new().
Step 2: Analyze given declaration
The declaration has new before class, which is invalid.
Final Answer:
The order of constraints is incorrect; class must come before new() -> Option B
Quick Check:
Constraint order matters: class before new() [OK]
Hint: Remember: class or struct first, then new() [OK]
Common Mistakes:
Placing new() before class
Omitting parentheses in new()
Thinking constraints order does not matter
5. You want to create a generic repository class that only accepts types which are classes, implement IDisposable, and have a parameterless constructor. Which is the correct declaration?
hard
A. class Repository<T> where T : IDisposable, class, new() { }
B. class Repository<T> where T : class, new(), IDisposable { }
C. class Repository<T> where T : new(), class, IDisposable { }
D. class Repository<T> where T : class, IDisposable, new() { }
Solution
Step 1: Understand constraint order rules
class must come first, then interfaces, then new().
Step 2: Check each option's order
class Repository<T> where T : class, IDisposable, new() { } follows correct order: class, IDisposable, new().
Step 3: Verify all constraints are included
class Repository<T> where T : class, IDisposable, new() { } includes all required constraints correctly.
Final Answer:
class Repository<T> where T : class, IDisposable, new() { } -> Option D
Quick Check:
Correct order: class, interfaces, new() [OK]
Hint: Order constraints: class, interfaces, then new() [OK]
Common Mistakes:
Placing new() before class
Mixing order of interfaces and class constraint
Omitting required constraints
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.