└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # 100 Must-Know C# Interview Questions in 2025 2 | 3 |
4 |

5 | 6 | web-and-mobile-development 7 | 8 |

9 | 10 | #### You can also find all 100 answers here 👉 [Devinterview.io - C#](https://devinterview.io/questions/web-and-mobile-development/c-sharp-interview-questions) 11 | 12 |
13 | 14 | ## 1. What is _C#_ and what are its key features? 15 | 16 | **C#**, pronounced "C-sharp," is an object-oriented, multi-paradigm programming language developed by **Microsoft** as part of its .NET initiative. It's widely used for developing applications targeting the Windows ecosystem. 17 | 18 | ### Key Features of C# 19 | 20 | 1. **Simplicity**: C# streamlines complex tasks, making common programming patterns more manageable. 21 | 22 | 2. **Type Safety**: It employs a robust type system that mitigates many common programming errors at compile time. 23 | 24 | 3. **Object-Oriented Design**: It encourages modular, reusable code structures through classes and interfaces. 25 | 26 | 4. **Scalability**: C# supports both small, quick programs and large, intricate applications. 27 | 28 | 5. **Cross-Language Support**: It integrates seamlessly with other languages in the .NET ecosystem, offering advantages such as unified debugging and code reuse. 29 | 30 | 6. **Language Interoperability**: Developers can leverage code from other languages integrated into .NET. 31 | 32 | 7. **Memory Management**: It uses automatic memory management, reducing the burden of manual memory allocation and deallocation. 33 | 34 | 8. **Asynchronous Programming**: C# provides powerful tools to create responsive applications, such as the `async` and `await` keywords. 35 | 36 | 9. **Integrated Development Environment (IDE)**: Visual Studio is a robust and popular tool for C# development, offering features like IntelliSense and debugging. 37 | 38 | 10. **Library Support**: C# is backed by a vast standard library that simplifies various tasks. 39 | 40 | 11. **Modern Features**: C# continues to evolve, leveraging contemporary software development concepts and practices. 41 | 42 | 12. **Suitability for Web Development**: C# is used in conjunction with ASP.NET for developing dynamic web applications and services. 43 | 44 | 13. **LINQ (Language-Integrated Query)**: C# provides LINQ, enabling developers to query collections akin to SQL. 45 | 46 | 14. **Built-In Security Features**: C# includes functionalities such as Code Access Security (CAS) and Role-Based Security. 47 | 48 | 15. **Native Code Execution**: C# applications are executed through the Common Language Runtime (CLR), offering platform independence. 49 | 50 | 16. **Exception Handling**: It utilizes a structured error-handling approach, making it easier to reason about potential code issues. 51 | 52 | 17. **Polymorphism and Inheritance**: These essential object-oriented concepts are foundational to C#. 53 | 54 | ### Memory Management in C# 55 | 56 | C# uses the **Garbage Collector (GC)** for automatic memory management. The GC identifies and removes objects that are no longer in use, optimizing memory consumption. However, improper memory handling can lead to memory leaks or inefficient GC performance, underscoring the need for developer awareness. 57 | 58 | ### Strong Types in C# 59 | 60 | One of the defining characteristics of C# is its strong type system. It enforces type checking at compile time, reducing the likelihood of data-related errors. This stringency extends to both **primitive types** (e.g., `int`, `float`, `bool`) and **user-defined types**. C# 7.0 onward introduced **"pattern matching"**, enhancing the language's handling of types and enabling straightforward type-based operations. 61 | 62 | ### Asynchronous Programming Support 63 | 64 | C# incorporates a task-based model for efficient asynchronous execution. This approach, facilitated by the `async` and `await` keywords, mitigates thread-related overhead typically associated with multithreading, bolstering application performance. 65 | 66 | ### Code Access Security 67 | 68 | Historically, C# applications implemented Code Access Security (CAS). This feature defined and enforced permissions for varying levels of privilege within an application. CAS has been gradually phased out in newer versions of .NET, but C# remains renowned for its robust security features. 69 |
70 | 71 | ## 2. Explain the basic structure of a _C# program_. 72 | 73 | Let's look at the basic structure of a C# program, including its key elements like **Namespaces**, **Classes**, **Methods**, **Variables**, **Keywords for types**, **Statements**, **Directives** and the **Main method**. 74 | 75 | ### Main Program Components 76 | 77 | - **Namespaces**: Serve as containers for related classes; they help prevent naming conflicts. The most commonly used namespace is `System`, which provides access to fundamental types, such as strings and exceptions. Examples: `System`, `System.Collections`, and `System.Text`. 78 | 79 | - **Class**: Acts as a blueprint for objects. A program can have multiple classes, but **only one of them should have the Main method.** Such a class is referred to as the "startup" class. Here is a basic example of the structure of the startup class. 80 | 81 | ```csharp 82 | namespace MyApp 83 | { 84 | class Program 85 | { 86 | static void Main() 87 | { 88 | // Program execution starts here. 89 | } 90 | } 91 | } 92 | ``` 93 | 94 | - **Method**: Represents a collection of statements that are grouped together to perform a specific operation. The Main method is the entry point for a C# application. 95 | 96 | - **Variables**: They store data that can be manipulated throughout the program. For instance, you can use a variable to keep track of score in a game or to store a user's input. 97 | 98 | - **Console Input/Output**: The `System.Console` class provides methods to read input from and write output to the console. 99 | 100 | - **Control Statements**: Such as `if-else` and `while`, help in altering the program's flow based on conditions. 101 | 102 | - **Comments**: These are non-executing lines used for documentation. In C#, a single line comment begins with `//`, and a multi-line comment starts with `/*` and ends with `*/`. 103 | 104 | - **Directives**: These are special instructions that tell the compiler to perform specific tasks. For instance, the `#include` directive is used to add the contents of a file to the source file during compilation, and `#define` is used to create symbolic constants. 105 | 106 | ### Code Example: Bricks Count 107 | 108 | Here is the C# code: 109 | 110 | ```csharp 111 | // Count the number of bricks in a pyramid 112 | using System; 113 | 114 | class Program 115 | { 116 | static void Main() 117 | { 118 | Console.Write("Enter the number of levels in the pyramid: "); 119 | int levels = int.Parse(Console.ReadLine()); 120 | 121 | int totalBricks = CalculateBricks(levels); 122 | Console.WriteLine($"Total bricks in the {levels}-level pyramid: {totalBricks}"); 123 | } 124 | 125 | static int CalculateBricks(int levels) 126 | { 127 | int bricksAtBase = levels * levels; 128 | return (bricksAtBase * (bricksAtBase + 1) * (2 * bricksAtBase + 1)) / 6; 129 | } 130 | } 131 | ``` 132 |
133 | 134 | ## 3. What are the different types of _data types_ available in _C#_? 135 | 136 | **C#** features a variety of data types, each tailored to specific data needs. These types are grouped under different categories that include: 137 | 138 | - **Value Types**: They store their own data and are distinct from one another. Examples include basic types like **int** and **float**, as well as **struct**. 139 | - **Reference Types**: These types store references to their data. **Classes**, **arrays**, and **delegates** are classic examples. 140 | - **Integral Types**: These are whole numbers, either signed or unsigned. 141 | - **Floating-Point Types**: These accommodate non-integer numbers. 142 | - **High-Precision Decimal Type**: Ideal for precise monetary and scientific calculations. 143 | - **Boolean Type**: Represents truth values. 144 | - **Character Types**: Specifically designed for holding characters and described in two flavors: **Uniocode** and **ASCII**. 145 | - **Text Types**: Specifically tailored for text like strings. 146 | 147 | ### Basic Types 148 | 149 | These are the ones that are used most commonly in regular programming tasks. 150 | 151 | #### `bool` (Boolean) 152 | 153 | It signifies either **true** or **false** in logical operations. 154 | 155 | - Storage Size: Not precise; generally 1 byte 156 | - Default Value: **false** 157 | - `True` Equivalents: Any non-zero numerical value; for instance, 1 is the same as **true**. Non-null object references are also **true**. 158 | - `False` Equivalents: **0**, **null**, or an empty object reference 159 | 160 | #### `char` (Character) 161 | 162 | This represents a single Unicode character and is enclosed in **single quotes**. 163 | 164 | - Storage Size: 2 bytes or 16 bits. 165 | - Minimum Value: '0' 166 | - Maximum Value: 'uffff' or '65,535' 167 | - Default Value: **null** 168 | 169 | #### `sbyte`, `byte`, `short`, `ushort`, `int`, and `uint` (Integral Types) 170 | 171 | `byte`, `short`, and `int` are the most often used members in most applications. 172 | 173 | | Data Type | Size in Bytes | Range for Signed Values | Default Value | 174 | |-----------|-------------------|-----------------------------|-------------------| 175 | | `sbyte` | 1 | -128 to 127 | 0 | 176 | | `byte` | 1 | 0 to 255 | 0 | 177 | | `short` | 2 | -32,768 to 32,767 | 0 | 178 | | `ushort` | 2 | 0 to 65,535 | 0 | 179 | | `int` | 4 | -2,147,483,648 to 2,147,483,647 | 0 | 180 | | `uint` | 4 | 0 to 4,294,967,295 | 0 | 181 | 182 | #### `long` and `ulong` 183 | 184 | These types are for very larger numbers, and they are usually associated with memory consumption. 185 | 186 | - **Size in Bytes**: **8** (64 bits) 187 | - **Range for Signed Values**: Approximately ±9.22 x 10$^{18}$ 188 | - **Default Value**: **0** for `long` and `ulong` 189 | 190 | #### `float` and `double` (Floating-Point Types) 191 | 192 | Both `float` and `double` can accommodate fractional values, but their precision varies. `double` allows for more significant digits. 193 | 194 | - **Size in Bytes**: 4 for `float` and 8 for `double` 195 | - **Precision**: 7 decimal places for `float` and 15 decimal places for `double` 196 | - **Default Value**: 0.0 197 | 198 | #### `decimal` (High-Precision Decimal Type) 199 | 200 | This type is used for precision financial and monetary calculations. 201 | 202 | - **Size in Bytes**: 16 (128 bits) 203 | - **Precision**: Up to 28 decimal places for both integral and fractional parts. 204 | - **Default Value**: 0.0M 205 | 206 | #### String and Object Types 207 | 208 | The **object** type is a **base type for all other types**, while the **string** type is specifically tailored for text storage. 209 | 210 | - **Storage Size**: Variable 211 | - **Example**: 212 | 213 | ```c# 214 | object obj = "Hello"; // An object 215 | string str = "Hello"; // A string 216 | ``` 217 | 218 | ### Other Types 219 | 220 | `struct`, `enum`, `Nullable`, `tuple`, `valueTuple` are among other types in C#. 221 | **Cards.dll** is the main Dynamic-Linked Library (DLL) file for the **Solitaire** game. The game needs access to visual assets and data configurations. The **Cards.dll** file provides the visual resources and supports specific functionalities for the game, such as drawing playing cards on the screen. This DLL might also contain card-specific details like symbols, suits, or card images. 222 | 223 | The **Cards.dll** file isn't intended for use in standalone applications but supports the Solitaire game. The DLL might include card-related resources created using tools like **Visual Studio** or third-party drawing software. 224 | 225 | ### Integrating Visual Cues 226 | 227 | Visual representations, such as card images, can enhance user experience, making the game more engaging and intuitive. The DLL is likely key to linking these visual cues with code logic. 228 | 229 | ### Code Example 230 | 231 | Here's a code snippet for providing a deck of cards using the Cards.dll: 232 | 233 | ```csharp 234 | // Import the Cards.dll assembly 235 | using Cards; 236 | 237 | // Create a new deck of cards from the DLL 238 | Deck myDeck = new Deck(); 239 | 240 | // Deal a card 241 | Card firstCard = myDeck.DrawACard(); 242 | ``` 243 |
244 | 245 | ## 4. What is the difference between _value types_ and _reference types_? 246 | 247 | Let's look at the difference between **Value Types** and **Reference Types**. 248 | 249 | ### Key Distinctions 250 | 251 | #### Data Storage 252 | 253 | - **Value Types**: Store the data in their memory space. Examples include primitive types like integers and floating-point numbers. 254 | - **Reference Types**: Store a reference to the data, which resides in the managed heap, and have dynamic storage size. 255 | 256 | #### Memory Management 257 | 258 | - **Value Types**: Managed by the stack. Memory is allocated and deallocated automatically within the scope of where they are defined. 259 | - **Reference Types**: Managed by the heap. Garbage Collector automatically allocates memory and reclaims it when the object is no longer referenced. 260 | 261 | #### Assignment Behavior 262 | 263 | - **Value Types**: Directly manipulate their allocated memory. Assigning one value type to another creates an independent copy. 264 | - **Reference Types**: Store a reference to the object's location in memory. Assigning a reference type to another only creates a new reference to the same object in memory. 265 | 266 | #### Performance 267 | 268 | - **Value Types**: Generally faster to access and manipulate because of their stack-based memory management. Ideal for smaller data types. 269 | - **Reference Types**: Slight performance overhead due to indirection (pointer dereferencing) when accessing data in heap memory. 270 | 271 | #### Nullability 272 | 273 | - **Value Types**: Cannot be `null`. They always have a defined value. 274 | - **Reference Types**: Can be `null`, especially if it's not been assigned an object. 275 | 276 | #### Type Categories 277 | 278 | - **Value Types**: Most primitive data types (int, float, bool, char, etc.), enums, and structs are value types. 279 | - **Reference Types**: Classes, arrays, strings, delegates, and objects of types that are derived from the base type `object` are reference types. 280 | 281 | ### Code Example: Value and Reference Types 282 | 283 | Here is the C# code: 284 | 285 | ```csharp 286 | using System; 287 | 288 | class ValueReferenceExample 289 | { 290 | public static void Main(string[] args) 291 | { 292 | int val1 = 10; // Value type: Example of a primitive type 293 | int val2 = val1; // val2 is a separate copy of the value 294 | 295 | // Now modifying val2 will not change val1 296 | val2 = 20; 297 | 298 | Console.WriteLine("val1: " + val1 + ", val2: " + val2); 299 | 300 | MyStruct struct1 = new MyStruct { Value = 5 }; // Value type: Example of a struct 301 | MyStruct struct2 = struct1; // struct2 is a separate copy 302 | struct2.Value = 10; 303 | Console.WriteLine("struct1: " + struct1.Value + ", struct2: " + struct2.Value); 304 | 305 | MyClass ref1 = new MyClass { SomeNumber = 7 }; // Reference type: Example of a class 306 | MyClass ref2 = ref1; // ref2 is a reference to the same object 307 | ref2.SomeNumber = 15; 308 | Console.WriteLine("ref1: " + ref1.SomeNumber + ", ref2: " + ref2.SomeNumber); 309 | 310 | string str1 = "Hello, World!"; // Reference type: Example of a string 311 | string str2 = str1; 312 | str2 += " Have a great day!"; // Modifying str2 will not change str1 313 | Console.WriteLine("str1: " + str1 + ", str2: " + str2); 314 | } 315 | } 316 | 317 | struct MyStruct 318 | { 319 | public int Value; 320 | } 321 | 322 | class MyClass 323 | { 324 | public int SomeNumber { get; set; } 325 | } 326 | ``` 327 |
328 | 329 | ## 5. What are _nullable types_ in _C#_? 330 | 331 | **Nullable types** are a special data type in C# that can represent both a regular value and `null`. It is a beneficial feature for representing data that might be absent or unknown. 332 | 333 | ### Key Considerations for Using Nullable Types 334 | 335 | - **Memory Consumption**: Data types with explicit sizes, such as `int` or `bool`, need more space in memory when converted to nullable types. 336 | 337 | - **Performance**: Nullable types might result in fewer optimizations, particularly with certain operations. 338 | 339 | - **Clarity**: They offer transparency about the possible absence of a value. 340 | 341 | ### The "null-conditional" operators 342 | 343 | In C#, there are dedicated **"null-conditional" operators** caters to appropriately performing actions for nullable types, ensuring that there is no NullReferenceException. Among these are `?.`, `??`, `??=`, and `?.[]`. 344 | 345 | ### Syntax Requirements for Nullable Types 346 | 347 | - Assigning a value: `int? nullableInt = 10;` 348 | 349 | - Assigning `null`: `nullableInt = null;` 350 | 351 | - Performing Operations: Before utilizing the value, ensure it's not null. 352 | 353 | ```csharp 354 | if (nullableInt.HasValue) { 355 | int result = nullableInt.Value; 356 | } 357 | ``` 358 | 359 | ### Common Application Scenarios 360 | 361 | - **Database Interactions**: Adaptability to designate if a field is not set. 362 | 363 | - **API Requests**: Effective communication to specify if the endpoint did not return a value as anticipated. 364 | 365 | - **User Inputs**: Allowing for the perception of a lack of explicit user input. 366 | 367 | - **Workflow Dependencies**: Identifying components that necessitate additional data to proceed. 368 |
369 | 370 | ## 6. Can you describe what _namespaces_ are and how they are used in _C#_? 371 | 372 | A key concept in C#, a **namespace** organizes code, allows for better code management, and prevents naming conflicts between different elements (such as classes, interfaces, and enums). 373 | 374 | **Namespaces** are particularly useful in larger projects and team-based development. 375 | 376 | ### Key Features 377 | 378 | 1. **Granularity**: Namespaces provide a way to group related pieces of code, making it easier to navigate your codebase. 379 | 2. **Uniqueness**: Every element in a namespace is guaranteed to have a unique name. 380 | 3. **Accessibility Control**: By default, members in a namespace are accessible only within the same namespace. You can use `public` and `internal` access modifiers to control this. 381 | 382 | ### Code Example: Basic Namespace 383 | 384 | Here is the C# code: 385 | 386 | ```csharp 387 | namespace MyNamespace 388 | { 389 | public class MyClass { /* ... */ } 390 | 391 | internal class MyInternalClass { /* ... */ } 392 | 393 | // This interface will be accessible across the entire project 394 | public interface IMyInterface { /* ... */ } 395 | } 396 | ``` 397 | 398 | ### Nested Namespace 399 | 400 | You can have nested namespaces to further organize your code. 401 | 402 | Here is the C# code: 403 | 404 | ```csharp 405 | namespace ParentNamespace 406 | { 407 | namespace ChildNamespace 408 | { 409 | public class ChildClass { /* ... */ } 410 | } 411 | } 412 | ``` 413 | 414 | **Consider**: ChildNamespace is distinct from a top-level namespace. 415 | 416 | ### Access 417 | 418 | Members of a **namespace** can be made more or less accessible using access modifiers. 419 | 420 | #### Code Example: Access Modifiers in a Namespace 421 | 422 | Here is the C# code: 423 | 424 | ```csharp 425 | namespace MyNamespace 426 | { 427 | // Without access modifier: internal by default 428 | class MyInternalClass { /* ... */ } 429 | 430 | // Public access modifier: accessible from any other code in the project 431 | public class MyClass { /* ... */ } 432 | 433 | // Private access modifier: not allowed in a namespace 434 | // Error: 'private' is not valid in this context 435 | // private void MyPrivateMethod() { /* ... */ } 436 | } 437 | ``` 438 | 439 | ### Using Directives 440 | 441 | Using `using` directives, you can avoid long, repetitive code. 442 | 443 | #### Code Example: Using Directives 444 | 445 | Here is the C# code: 446 | 447 | ```csharp 448 | using System; 449 | using MyNamespace; // this is a user-defined namespace 450 | 451 | // You can now directly use MyNamespace 452 | class Program 453 | { 454 | static void Main() 455 | { 456 | MyClass myObj = new MyClass(); 457 | Console.WriteLine("MyObject is created"); 458 | } 459 | } 460 | ``` 461 | 462 | ### Best Practices 463 | 464 | - **Consistency**: Decide on a consistent namespace naming convention, and ensure team members adhere to it. 465 | - **Relevance**: Use meaningful and descriptive names for your namespaces. A good practice is a reverse domain name, like `MyCompany.MyProduct`. 466 | - **Modularity**: Keep your namespaces well-structured and avoid making them too large, which can be counterproductive. 467 | 468 | ### Common Built-In .NET Namespaces 469 | 470 | - **System**: Fundamental types and base types. 471 | - **System.Collections**: Implementations of standard collection classes (like lists, dictionaries, and queues). 472 | - **System.IO**: Input and output, including file operations. 473 | - **System.Linq**: Language Integrated Query (LINQ) functionality. 474 | 475 | ### Common Namespaces 476 | 477 | - **System.Data**: Managed code for accessing data from relational data sources. 478 | - **System.Threading**: Enables multi-threading in applications. 479 | - **System.Xml**: Provides support for processing XML. 480 |
481 | 482 | ## 7. Explain the concept of _boxing_ and _unboxing_ in _C#_. 483 | 484 | **Boxing** is the process of converting a **value type** (struct) to a **reference type** (object) so it can be assigned to a variable of type `object` or an interface. Conversely, **unboxing** is the reverse operation. 485 | 486 | ### Mechanism 487 | 488 | - **Boxing**: When a value type is assigned to an `object`-typed variable or when it's passed as a method argument that expects an `object` or an interface type, the CLR boxes the value type, creating a reference-type object that holds the value. 489 | 490 | - **Unboxing**: The CLR extracts the original value type from the object, provided the object actually contains such a value. A runtime error occurs if the object holds a different type. 491 | 492 | ### Implications and Performance Considerations 493 | 494 | - **Performance**: Boxing and unboxing involve overhead due to memory allocation (when boxing) and type checks during unboxing. They are, therefore, less efficient than direct interactions with value types. 495 | 496 | - **Garbage Collection**: More aggressive memory management for short-lived objects could be necessary since **boxed objects reside on the heap**, subject to Garbage Collection. 497 | 498 | - **Potential for Errors**: Unboxing operations might fail with an `InvalidCastException` if the object's type doesn't match the expected value type. 499 | 500 | - **Type Mismatch**: There's a risk of unexpected behavior if types get mixed up, especially when unboxing. 501 | 502 | ### Code Example: Boxing and Unboxing 503 | 504 | Here is the C# code: 505 | 506 | ```csharp 507 | int number = 42; 508 | 509 | // Boxing: Converts integer to object 510 | object boxedNumber = number; 511 | 512 | // Unboxing: Converts object to integer 513 | int unboxedNumber = (int)boxedNumber; 514 | 515 | // This will throw an InvalidCastException 516 | // double potentialError = (double) boxedNumber; 517 | ``` 518 |
519 | 520 | ## 8. What is _Type Casting_ and what are its types in _C#_? 521 | 522 | **Type casting**, in the context of C#, refers to the explicit and implicit conversion of data types. While explicit casting might lead to data loss, implicit casting is carried out by the C# compiler, ensuring safe conversion. 523 | 524 | ### Implicit Casting 525 | 526 | This form of casting is **automatic** and occurs when there is **no risk of data loss**. For instance, an `int` can be automatically cast to a `long` as there is no possibility of truncation. 527 | 528 | ### Explicit Casting 529 | 530 | This form of casting must be done manually and is necessary when there is a risk of data loss. For example, when converting a `double` to an `int`, data loss due to truncation could occur. C# requires you to explicitly indicate such conversion, and if the conversion is not possible, it throws a `System.InvalidCastException`. 531 | 532 | ### Using `as` Operand 533 | 534 | If you are sure that an object can be cast to a specific type, use the `as` operand for optimization. If the conversion is possible, the operand returns an object of the specified type; otherwise, it returns `null`. 535 | 536 | ### The `is` Operator for Type Checking 537 | 538 | With the `is` operator, you can test whether an object is compatible with a specific type. This tool is very useful to prevent `InvalidCastException` errors. 539 |
540 | 541 | ## 9. What are _operators_ in _C#_ and can you provide examples? 542 | 543 | **Operators** in C# are symbols or keywords responsible for specific program actions, such as basic arithmetic, logical evaluations, or assignment. 544 | 545 | ### Basic Operators 546 | 547 | #### Arithmetic Operators 548 | 549 | - **Addition**: `+` 550 | - **Subtraction**: `-` 551 | - **Multiplication**: `*` 552 | - **Division**: `/` 553 | - **Modulus**: `%` (remainder of division) 554 | 555 | ```csharp 556 | int result = 10 % 3; // Output: 1 (the remainder of 10 divided by 3) 557 | ``` 558 | 559 | #### Comparison Operators 560 | 561 | - **Equal to**: `==` 562 | - **Not equal to**: `!=` 563 | - **Greater than**: `>` 564 | - **Less than**: `<` 565 | - **Greater than or equal to**: `>=` 566 | - **Less than or equal to**: `<=` 567 | 568 | ```csharp 569 | bool isGreater = 5 > 3; // Output: true 570 | ``` 571 | 572 | #### Conditional Operators 573 | 574 | - **AND (both conditions are true)**: `&&` 575 | - **OR (at least one condition is true)**: `||` 576 | 577 | ```csharp 578 | bool conditionMet = (5 > 3) && (7 < 10); // Output: true, both conditions are true 579 | ``` 580 | 581 | - **Ternary**: `?` and `:` 582 | ```csharp 583 | int max = (5 > 3) ? 5 : 3; // Output: 5 (if true, takes the first value, if false, takes the second value) 584 | ``` 585 | 586 | - **Null Coalescing**: `??` 587 | ```csharp 588 | string name = incomingName ?? "Default Name"; // Output: The value in incomingName, or "Default Name" if incomingName is null 589 | ``` 590 | 591 | #### Bitwise Operators 592 | 593 | These operators perform actions at the bit level. 594 | 595 | - **AND**: `&` 596 | - **OR**: `|` 597 | - **XOR**: `^` (Exclusive OR) 598 | - **NOT**: `~` (Unary complement) 599 | - **Shift left**: `<<` 600 | - **Shift right**: `>>` 601 | 602 | ```csharp 603 | int bitwiseAndResult = 5 & 3; // Output: 1 (bitwise AND of 5 and 3 is 1) 604 | ``` 605 | 606 | #### Assignment Operators 607 | 608 | - **Simple assignment**: `=` 609 | - **Add then assign**: `+=` 610 | - **Subtract then assign**: `-=` 611 | - **Multiply then assign**: `*=` 612 | - **Divide then assign**: `/=` 613 | - **Modulus then assign**: `%=` 614 | - **AND then assign**: `&=` 615 | - **OR then assign**: `|=` 616 | 617 | ```csharp 618 | int num = 5; 619 | num += 3; // num is now 8 620 | ``` 621 |
622 | 623 | ## 10. What is the difference between `==` _operator_ and `.Equals()` _method_? 624 | 625 | The `==` operator in C# is used to compare two objects for reference equality, meaning it checks whether the two objects are the same instance in memory. On the other hand, the `.Equals()` method is used to compare the actual values of the two objects, based on how the method is implemented for a particular class. 626 | 627 | For value types like `int`, `bool`, `double`, and `structs`, the `==` operator compares the values, whereas for reference types like `string` and custom classes, it compares the references. 628 | 629 | It's important to note that the behavior of the `==` operator can be overridden for reference types by overloading the operator, allowing it to compare values instead of references. 630 | 631 | The `.Equals()` method can also be overridden in classes to provide custom equality comparisons. By default, it behaves like the `==` operator for reference types but can be customized to compare values instead. 632 |
633 | 634 | ## 11. What is the purpose of the `var` _keyword_ in _C#_? 635 | 636 | Introduced in C# 3.0 along with the Language-Integrated Query (LINQ) features, the `var` keyword primarily serves to **reduce redundancy**. 637 | 638 | ### Key Benefits 639 | 640 | - **Code Conciseness**: It streamlines code by inferring types, especially with complex types or generic data structures. 641 | 642 | - **Dynamic and Anonymous Types Support**: It's useful when using dynamic types or initializing objects with an anonymous type; a feature useful in LINQ queries. 643 | 644 | ### Avoid Misusing `var` 645 | 646 | It's important to use `var` with caution to prevent these issues: 647 | 648 | - **Type Clarity**: Incorporating explicit type declarations can enhance code clarity, especially for beginners or when working with inherited code. 649 | 650 | - **Code Readability for Method Chaining**: Avoid using `var` excessively when chaining methods to maintain readability. 651 | 652 | ### Best Practices and Common Use-Cases 653 | 654 | - **Initialization**: Use `var` while initializing; it helps adapt to object type changes, reduces redundancy, and aligns with the DRY (Don't Repeat Yourself) principle. 655 | 656 | - **For-Each Loops with Collections**: It's standard practice to use `var` in for-each loops when iterating through collections**. 657 | 658 | - **Complex or Generic Types**: `var` brings clarity and brevity when working with such types. 659 | 660 | ### Code Example: Misusing `var` 661 | 662 | Here is the c# code: 663 | 664 | ```csharp 665 | var user = GetUser(); 666 | var customer = LookUpCustomer(user); // What's the type of customer? 667 | 668 | // This would be better for clarity: 669 | Customer customer = LookUpCustomer(user); 670 | ``` 671 | This code shows the potential confusion that can stem from not explicitly declaring types. In this example, using `var` might not communicate the "Customer" type as clearly or immediately as an explicit type declaration. 672 |
673 | 674 | ## 12. What are the differences between `const` and `readonly` _keywords_? 675 | 676 | **C#** supports two mechanisms for creating **immutable** fields: **`const`** and **`readonly`**. 677 | 678 | ### Key Distinctions 679 | 680 | - **Initialization**: `const` fields are initialized when declared, while `readonly` fields can be initialized at the point of declaration or in the class constructor. 681 | 682 | - **Visibility**: `readonly` fields allow for differing values within different class instances, whereas `const` ensures the same value across all instances. 683 | 684 | - **Type Compatibility**: `const` fields are limited to primitive data types, `String`, and `null`. `readonly` can be utilized with any data type. 685 | 686 | - **Compile-Time/Run-Time**: `const` fields are evaluated at compile time. On the contrary, `readonly` fields are evaluated at run-time, fittingly appealing to scenarios that necessitate a run-time reference or state. 687 | 688 | ### Code Example: const vs. readonly 689 | 690 | Here is the C# code: 691 | 692 | ```csharp 693 | public class Example { 694 | private readonly int readOnlyField; 695 | public const int constField = 5; 696 | 697 | public Example(int value) { 698 | readOnlyField = value; 699 | } 700 | 701 | public void AssignValueToReadOnlyField(int value) { 702 | readOnlyField = value; // Will cause a compilation error 703 | } 704 | } 705 | ``` 706 | 707 | Note that the `readOnlyField` is assigned its value either in the constructor or at declaration. Once it has a value, that value is unalterable. This invariance ensures its immutability. Likewise, `constField` is initialized with a value at the time of declaration and is unalterable for the duration of the program. 708 |
709 | 710 | ## 13. How does `checked` and `unchecked` _context_ affect arithmetic operations? 711 | 712 | In C#, the enablers `checked` and `unchecked` ensure more predictable behavior when using specific arithmetic operations. By default, C# employs overflow checking, but you can toggle to overflow wrapping using appropriate blocks. 713 | 714 | ### Context Control Keywords 715 | 716 | - **checked**: Forces operations to produce exceptions for overflow. 717 | - **unchecked**: Causes operations to wrap on overflow. 718 | 719 | ### When to Use Each Context 720 | 721 | - **checked**: Ideal when you require accurate numeric results to guarantee that potential overflows are detected and handled. 722 | 723 | - **unchecked**: Primarily used to enhance performance in scenarios where the logic or the expected input range ensures that overflows are less probable or inconsequential. 724 | 725 | ### C# Code Example 726 | 727 | Here is the C# code: 728 | 729 | ```csharp 730 | using System; 731 | 732 | public class Program 733 | { 734 | public static void Main() 735 | { 736 | int a = int.MaxValue; 737 | int b = 1; 738 | 739 | Console.WriteLine("Using checked context:"); 740 | try { 741 | checked { 742 | int c = a + b; 743 | Console.WriteLine($"Sum: {c}"); 744 | } 745 | } 746 | catch (OverflowException) { 747 | Console.WriteLine("Overflow detected!"); 748 | } 749 | 750 | Console.WriteLine("\nUsing unchecked context:"); 751 | unchecked { 752 | int d = a + b; 753 | Console.WriteLine($"Sum (unlike c#): {d}"); 754 | } 755 | } 756 | } 757 | ``` 758 |
759 | 760 | ## 14. What are the different ways to handle _errors_ in _C#_? 761 | 762 | **C#** offers multiple mechanisms for handling errors, from traditional **exception handling** to contemporary **asynchronous error management** strategies. 763 | 764 | ### 5 Key Methods for Error Handling in C# 765 | 766 | 1. **Exception Handling**: Based on `try-catch`, primarily for synchronous flows but also compatible with some asynchronous scenarios. Exceptions are caught and processed within `catch` blocks. 767 | 768 | 2. **Logging and Monitoring**: Involves using services like `ILogger` or specialized tools to capture, evaluate, and report application errors. 769 | 770 | 3. **HTTP Status Codes**: Typically utilized in web applications to convey the status of a web request. RESTful services also often use these codes for error management. 771 | 772 | 4. **Return Values**: Methods and functions can provide customized return values to signify different error states. 773 | 774 | 5. **Task\ and Task**: Primarily for asynchronous programming, indicating error states through `Task` results (`.Result`) or `Task` members (`.IsFaulted`). 775 | 776 | While exceptions represent unexpected errors, the other methods can be better suited for the controlled handling of anticipated issues. 777 | 778 | For instance, a missing email in a registration form might be considered a normal scenario and should be conveyed back to the user via a **return value**, rather than triggering an exception. 779 |
780 | 781 | ## 15. Explain the role of the _garbage collector_ in _.NET_. 782 | 783 | The **Garbage Collector** (GC) is a key feature in **.NET** that automates memory management. Rather than requiring manual memory deallocation (as seen in languages like C/C++), the GC identifies and recovers memory that's no longer in use. 784 | 785 | ### Benefits of Automatic Memory Management 786 | 787 | - **Reduced Memory Leaks**: The GC helps prevent leaks by reclaiming memory that's no longer accessible, even if the programmer forgets to free it. 788 | - **Simplified Memory Management**: Developers are freed from tedious tasks like memory allocation, tracking object lifetimes, and memory deallocation. 789 | - **Protection from Use-after-Free Bugs**: Segmentation faults and other issues caused by accessing memory that's been freed are avoided. 790 | 791 | ### Fundamentals of the Garbage Collector 792 | 793 | - **Trigger Mechanism**: The GC is triggered in the background whenever certain memory thresholds are reached, reducing interruption to your program's execution. 794 | 795 | - **Process Overview**: It divides memory into three generations, each associated with a different cleanup frequency. Most objects are initially allocated in the first generation (Gen0). When the GC cleans up Gen0, it may promote some objects to Gen1, and so forth. The idea is that, over time, surviving objects are promoted to higher generations and require less frequent cleanup. 796 | 797 | - **Mark and Sweep**: During the cleanup cycle, the GC marks all reachable objects and then reclaims the memory occupied by objects that weren't marked. This process ensures that only inaccessible objects are collected. 798 | 799 | ### Recommendations for Handling Memory in .NET 800 | 801 | - **Limit High-Frequency Object Instantiation**: Frequent creation and destruction of small, short-lived objects can lead to inefficient GC usage. Consider using object pools for such scenarios. 802 | 803 | - **Dispose of Unmanaged Resources**: Certain resources, like file handles or database connections, may not be managed by the GC alone. It's crucial to release them explicitly, typically by implementing the `IDisposable` pattern. 804 | 805 | - **Consider Generational Behavior**: The GC's generational approach means that data-heavy long-lived objects (LLDs) could remain in memory for extended periods. Be mindful of LLDs' persistence and their impact on memory consumption. 806 | 807 | ### Code Example: Explicit Disposal with `using` 808 | 809 | Here is the C# code: 810 | 811 | ```csharp 812 | using System; 813 | 814 | public class ResourceUser : IDisposable 815 | { 816 | private IntPtr resource; // Example unmanaged resource 817 | 818 | public ResourceUser() 819 | { 820 | resource = SomeNativeLibrary.AllocateResource(); 821 | } 822 | 823 | public void Dispose() 824 | { 825 | SomeNativeLibrary.DeallocateResource(resource); 826 | GC.SuppressFinalize(this); // Omit if Dispose and the finalizer aren't both defined 827 | } 828 | } 829 | 830 | public static class Program 831 | { 832 | public static void Main() 833 | { 834 | using(var resourceUser = new ResourceUser()) 835 | { 836 | // Use the resource 837 | } 838 | // resourceUser is automatically disposed here 839 | } 840 | } 841 | ``` 842 |
843 | 844 | 845 | 846 | #### Explore all 100 answers here 👉 [Devinterview.io - C#](https://devinterview.io/questions/web-and-mobile-development/c-sharp-interview-questions) 847 | 848 |
849 | 850 | 851 | web-and-mobile-development 852 | 853 |

854 | 855 | --------------------------------------------------------------------------------