0
0
C Sharp (C#)programming~15 mins

Inspecting methods and properties in C Sharp (C#) - Deep Dive

Choose your learning style9 modes available
Overview - Inspecting methods and properties
What is it?
Inspecting methods and properties means looking inside a class or object to see what actions it can perform (methods) and what information it holds (properties). This is done without changing the class, just by examining it. In C#, this is often done using reflection, a way to explore types and members at runtime. It helps programmers understand and use code they didn't write or that changes dynamically.
Why it matters
Without the ability to inspect methods and properties, programmers would struggle to work with unknown or changing code. Imagine trying to use a tool without knowing what buttons it has or what they do. Reflection lets you discover these details on the fly, enabling flexible programs like plugins, serializers, or debuggers. Without it, software would be less adaptable and harder to maintain.
Where it fits
Before learning this, you should know basic C# classes, methods, and properties. Understanding how to write and use classes is essential. After this, you can explore advanced topics like dynamic programming, custom attributes, or building frameworks that adapt to different types at runtime.
Mental Model
Core Idea
Inspecting methods and properties is like opening a toolbox to see what tools are inside and how to use them without taking them apart.
Think of it like...
It's like looking at a car's dashboard and controls to understand what functions the car has and how to operate them, without opening the engine or changing anything.
┌─────────────────────────────┐
│        Class/Object          │
│ ┌───────────────┐           │
│ │  Properties   │  <-- Info  │
│ │  (Data held)  │           │
│ └───────────────┘           │
│ ┌───────────────┐           │
│ │   Methods     │  <-- Actions│
│ │ (Functions)   │           │
│ └───────────────┘           │
└─────────────┬───────────────┘
              │
              ▼
      Reflection inspects
      these parts at runtime
Build-Up - 7 Steps
1
FoundationUnderstanding Classes, Methods, Properties
🤔
Concept: Learn what classes, methods, and properties are in C#.
A class is like a blueprint for objects. Methods are actions the object can do. Properties hold information about the object. For example: public class Car { public string Color { get; set; } // Property public void Drive() { // Method Console.WriteLine("Driving"); } }
Result
You understand that classes group data (properties) and actions (methods) together.
Knowing the building blocks of classes is essential before you can inspect or manipulate them.
2
FoundationWhat is Reflection in C#?
🤔
Concept: Reflection lets you look at types and members during program execution.
Reflection is a feature in C# that allows your program to examine its own structure or other code. For example, you can find out what methods a class has or what properties it contains without calling them directly. Example: Type type = typeof(Car); Console.WriteLine(type.Name); // Outputs 'Car'
Result
You can get basic info about a class type at runtime.
Reflection opens the door to dynamic inspection and flexible programming.
3
IntermediateListing Methods of a Class
🤔Before reading on: do you think you can get method names directly from an object instance or only from its type? Commit to your answer.
Concept: You learn how to get all method names from a class using reflection.
Use the GetMethods() method on a Type object to get all methods. Example: Type type = typeof(Car); var methods = type.GetMethods(); foreach(var method in methods) { Console.WriteLine(method.Name); } This prints all public methods, including inherited ones.
Result
You see a list of method names like 'Drive', 'ToString', 'Equals', etc.
Understanding that methods are part of the type metadata helps you explore what actions an object can perform.
4
IntermediateAccessing Properties via Reflection
🤔Before reading on: do you think properties are treated the same as fields in reflection? Commit to your answer.
Concept: Learn to get property information and values from an object at runtime.
Use GetProperties() to list properties. You can also read or write property values dynamically. Example: Car car = new Car { Color = "Red" }; Type type = car.GetType(); var props = type.GetProperties(); foreach(var prop in props) { Console.WriteLine($"{prop.Name} = {prop.GetValue(car)}"); } This prints 'Color = Red'.
Result
You can see property names and their current values on an object.
Knowing how to read and write properties dynamically enables flexible code that adapts to different objects.
5
IntermediateFiltering Methods and Properties
🤔Before reading on: do you think reflection returns only public members by default or all members including private? Commit to your answer.
Concept: Learn to filter methods and properties by visibility or other criteria.
Reflection methods accept BindingFlags to specify what members to include. Example: var methods = type.GetMethods(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); You can also filter by name, static vs instance, or declared only in the class.
Result
You get a precise list of members matching your criteria.
Filtering helps avoid noise and focus on relevant members, improving performance and clarity.
6
AdvancedInvoking Methods Dynamically
🤔Before reading on: do you think you can call a method using reflection without knowing its name at compile time? Commit to your answer.
Concept: Learn to call methods on objects dynamically using reflection.
Use MethodInfo.Invoke to run a method by name. Example: Car car = new Car(); Type type = car.GetType(); var method = type.GetMethod("Drive"); method.Invoke(car, null); // Calls car.Drive()
Result
The method runs and prints 'Driving'.
Dynamic invocation allows programs to adapt behavior at runtime, useful for plugins or scripting.
7
ExpertPerformance and Security Considerations
🤔Before reading on: do you think reflection is as fast as direct method calls? Commit to your answer.
Concept: Understand the costs and risks of using reflection in production code.
Reflection is slower than direct calls because it uses metadata and runtime checks. It can also expose private members, risking security or breaking encapsulation. Use it carefully, cache results, and avoid overuse. Example: Repeatedly calling GetMethod inside a loop hurts performance. Use compiled expressions or source generators for better speed.
Result
You know when to avoid reflection or optimize its use.
Knowing reflection's limits prevents bugs and performance problems in real applications.
Under the Hood
Reflection works by accessing the metadata stored in the compiled assembly. This metadata describes all types, their members, and attributes. At runtime, the CLR (Common Language Runtime) reads this metadata to provide information about types and members. When you call reflection methods, the runtime looks up this metadata and returns objects representing methods, properties, and other members. Invoking methods uses late binding, which means the method is found and called dynamically rather than at compile time.
Why designed this way?
Reflection was designed to enable dynamic programming and tooling support in .NET. It allows programs to inspect and modify behavior without recompilation. The tradeoff was some performance cost and complexity, but the flexibility gained was worth it. Alternatives like code generation or dynamic languages exist, but reflection provides a unified, type-safe way to inspect code.
┌───────────────────────────────┐
│        Compiled Assembly       │
│ ┌───────────────────────────┐ │
│ │       Metadata Table       │ │
│ │ - Types                   │ │
│ │ - Methods                 │ │
│ │ - Properties              │ │
│ └─────────────┬─────────────┘ │
│               │               │
│       CLR Runtime Accesses    │
│               │               │
│ ┌─────────────▼─────────────┐ │
│ │      Reflection API        │ │
│ │ - Type                    │ │
│ │ - MethodInfo              │ │
│ │ - PropertyInfo            │ │
│ └─────────────┬─────────────┘ │
│               │               │
│       Your C# Program Calls  │
│               │               │
│ ┌─────────────▼─────────────┐ │
│ │  Dynamic Inspection & Call │ │
│ └───────────────────────────┘ │
└───────────────────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does reflection allow you to change private fields directly? Commit to yes or no.
Common Belief:Reflection can be used to freely change any private field or method without restrictions.
Tap to reveal reality
Reality:While reflection can access private members, some security settings or runtime environments restrict this. Also, changing private members can break encapsulation and cause unexpected behavior.
Why it matters:Assuming unrestricted access can lead to fragile code that breaks in different environments or future versions.
Quick: Is reflection as fast as normal method calls? Commit to yes or no.
Common Belief:Reflection calls are just as fast as normal method calls.
Tap to reveal reality
Reality:Reflection is slower because it uses metadata lookups and late binding, which add overhead compared to direct calls.
Why it matters:Using reflection in performance-critical code without care can cause slowdowns.
Quick: Does GetMethods() return only methods declared in the class? Commit to yes or no.
Common Belief:GetMethods() returns only the methods declared in the class you inspect.
Tap to reveal reality
Reality:GetMethods() returns all public methods including those inherited from base classes unless filtered.
Why it matters:Misunderstanding this can cause confusion when unexpected methods appear in the list.
Quick: Can you use reflection to call a method without knowing its signature? Commit to yes or no.
Common Belief:You can call any method with reflection without knowing its parameters or signature.
Tap to reveal reality
Reality:You must know the method's parameters to call it correctly; otherwise, you get errors.
Why it matters:Incorrect assumptions lead to runtime exceptions and bugs.
Expert Zone
1
Reflection metadata is cached internally by the runtime, but repeated calls to reflection methods can still be costly; caching MethodInfo or PropertyInfo yourself improves performance.
2
Attributes on methods and properties can be inspected via reflection to add metadata-driven behavior, enabling powerful frameworks and tools.
3
Reflection can be combined with Expression Trees or source generators to generate code at compile time, reducing runtime overhead.
When NOT to use
Avoid reflection in tight loops or performance-critical paths; prefer direct calls or generated code. For dynamic behavior, consider dynamic keyword or source generators. Reflection is also not suitable when strict security or sandboxing is required.
Production Patterns
Reflection is widely used in serialization libraries (like JSON serializers), dependency injection frameworks, testing tools, and plugin systems where code must adapt to unknown types or members at runtime.
Connections
Dynamic Programming
Reflection enables dynamic programming by allowing runtime type inspection and method invocation.
Understanding reflection helps grasp how dynamic languages or features work under the hood in static languages like C#.
Metadata in Compilers
Reflection reads metadata generated by the compiler to provide information about code structure.
Knowing how compilers embed metadata clarifies how reflection can access detailed type information.
Introspection in Biology
Both reflection and biological introspection involve examining internal structure without altering it.
Seeing reflection as a form of introspection helps appreciate its role in understanding complex systems safely.
Common Pitfalls
#1Trying to call a method with wrong parameters using reflection.
Wrong approach:var method = type.GetMethod("Drive"); method.Invoke(car, new object[] { "fast" }); // Drive() has no parameters, this causes error
Correct approach:var method = type.GetMethod("Drive"); method.Invoke(car, null); // Correct: no parameters
Root cause:Misunderstanding the method signature leads to passing incorrect arguments.
#2Assuming GetMethods() returns only declared methods.
Wrong approach:var methods = type.GetMethods(); // Expecting only Car's methods, but gets inherited ones too
Correct approach:var methods = type.GetMethods(System.Reflection.BindingFlags.DeclaredOnly | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
Root cause:Not using BindingFlags to filter methods causes unexpected results.
#3Using reflection inside a performance-critical loop without caching.
Wrong approach:for(int i=0; i<1000; i++) { var method = type.GetMethod("Drive"); method.Invoke(car, null); }
Correct approach:var method = type.GetMethod("Drive"); for(int i=0; i<1000; i++) { method.Invoke(car, null); }
Root cause:Repeatedly looking up MethodInfo wastes time; caching avoids this.
Key Takeaways
Inspecting methods and properties lets you explore and use code dynamically without prior knowledge of its details.
Reflection in C# accesses metadata at runtime to reveal types, methods, and properties, enabling flexible and adaptive programs.
While powerful, reflection has performance costs and security considerations that require careful use.
Filtering and caching reflection results improve efficiency and clarity in real-world applications.
Understanding reflection unlocks advanced programming techniques like dynamic invocation, serialization, and plugin architectures.