Top C# Interview Questions with Answers
Explanation: C# is a modern, object-oriented programming language developed by Microsoft as part of the .NET Framework. It is used to build a wide range of applications, from desktop to web and mobile applications.
// Simple "Hello, World!" in C# class Program { static void Main() { Console.WriteLine("Hello, World!"); } }
Explanation: C# supports several key features like Object-Oriented Programming (OOP), strong type-checking, garbage collection, and rich class libraries. It is also known for its interoperability with other .NET languages and its simplicity in syntax.
// Example of Object-Oriented Programming (OOP) in C# class Car { public string Brand { get; set; } public string Model { get; set; } public void DisplayInfo() { Console.WriteLine($"Brand: {Brand}, Model: {Model}"); } } class Program { static void Main() { Car myCar = new Car { Brand = "Toyota", Model = "Corolla" }; myCar.DisplayInfo(); } }
Explanation: C# is a high-level, garbage-collected language, whereas C++ is a low-level language that provides more control over system resources. C# is more suitable for Windows-based applications, while C++ is used in system programming, game development, and performance-critical applications.
// Simple C# vs C++ Code Example // C# example class HelloWorld { static void Main() { Console.WriteLine("Hello from C#"); } } // C++ example #includeusing namespace std; int main() { cout << "Hello from C++" << endl; return 0; }
Explanation: The Common Language Runtime (CLR) is the runtime environment of the .NET Framework. It manages memory, exception handling, garbage collection, and more. CLR allows the integration of different languages, enabling them to work together under the same runtime.
// C# code running on CLR class Program { static void Main() { Console.WriteLine("CLR handles memory management."); } }
Explanation: Value types store the actual data and are typically stored on the stack (e.g., int, char, struct). Reference types store references to the data and are stored on the heap (e.g., objects, arrays, classes). When you assign a value type to another, it copies the value. With reference types, only the reference is copied.
// Value Type Example (int) int x = 5; int y = x; // y is a copy of x // Reference Type Example (object) object a = new object(); object b = a; // b is a reference to a
Explanation: A namespace is a container for classes, structs, enums, and delegates. It helps organize code and avoid naming conflicts. In C#, the `namespace` keyword is used to declare namespaces.
// Example of namespace in C# namespace VehicleNamespace { public class Car { public string Brand { get; set; } public string Model { get; set; } public void DisplayInfo() { Console.WriteLine($"Brand: {Brand}, Model: {Model}"); } } } class Program { static void Main() { VehicleNamespace.Car myCar = new VehicleNamespace.Car { Brand = "Toyota", Model = "Corolla" }; myCar.DisplayInfo(); } }
Explanation: An assembly is a compiled code library in C#. It can be a .DLL or .EXE file and contains metadata, code, and other resources. Assemblies are used by the CLR to load and execute code.
// Example of Assembly usage using System.Reflection; class Program { static void Main() { Assembly assembly = Assembly.GetExecutingAssembly(); Console.WriteLine("Assembly Name: " + assembly.FullName); } }
Explanation: Managed code is written in languages like C#, which run under the control of the CLR. Unmanaged code, like C or C++, runs directly on the hardware and is not subject to the CLR's garbage collection and other runtime features.
// Managed code example (C#) class Program { static void Main() { Console.WriteLine("Managed Code is run under the CLR."); } }
Explanation: The "==" operator checks if two operands reference the same object, while `.Equals()` checks if the contents of two objects are the same. For value types, they behave the same, but for reference types, `Equals()` is more reliable.
// Example of "==" vs ".Equals()" class Program { static void Main() { string str1 = "Hello"; string str2 = "Hello"; string str3 = new string("Hello".ToCharArray()); Console.WriteLine(str1 == str2); // True, compares references Console.WriteLine(str1.Equals(str3)); // True, compares content } }
Explanation: Boxing is the process of converting a value type to a reference type, whereas unboxing is the reverse process, converting a reference type back to a value type. Boxing involves storing a value type in an object, and unboxing retrieves the value from the object.
// Example of Boxing and Unboxing class Program { static void Main() { int x = 42; object obj = x; // Boxing int y = (int)obj; // Unboxing Console.WriteLine(y); } }
Explanation: The four pillars of Object-Oriented Programming (OOP) are:
- Encapsulation: Bundling data and methods that operate on the data within a class.
- Abstraction: Hiding implementation details and showing only essential features.
- Inheritance: Deriving new classes from existing ones to reuse code.
- Polymorphism: The ability to take many forms, typically through method overriding or interfaces.
// Example of OOP pillars in C# public class Animal { public virtual void Speak() { Console.WriteLine("Animal speaks"); } } public class Dog : Animal { public override void Speak() // Polymorphism (overriding) { Console.WriteLine("Dog barks"); } } class Program { static void Main() { Animal myAnimal = new Animal(); Animal myDog = new Dog(); // Inheritance and Polymorphism myAnimal.Speak(); myDog.Speak(); // Polymorphism } }
Explanation: Inheritance allows a class (child class) to inherit methods and properties from another class (base class). This promotes code reuse and establishes a relationship between the base and derived classes.
// Example of inheritance in C# class Animal { public void Eat() => Console.WriteLine("Eating..."); } class Dog : Animal { public void Bark() => Console.WriteLine("Barking..."); } class Program { static void Main() { Dog dog = new Dog(); dog.Eat(); // Inherited method dog.Bark(); // Derived class method } }
Explanation: Polymorphism allows objects of different types to be treated as objects of a common base type. In C#, polymorphism is implemented through method overriding and interfaces. It enables method calls to behave differently based on the object type.
// Example of polymorphism in C# public class Animal { public virtual void Speak() { Console.WriteLine("Animal speaks"); } } public class Cat : Animal { public override void Speak() // Method overriding { Console.WriteLine("Cat meows"); } } class Program { static void Main() { Animal myCat = new Cat(); // Polymorphism myCat.Speak(); // Outputs: Cat meows } }
Explanation: Encapsulation is the practice of keeping fields (data) and methods (functions) together in a class and restricting access to some of the object's components. It's achieved using access modifiers like `private`, `protected`, and `public`.
// Example of encapsulation in C# class Person { private string name; // Private field public string Name // Public property { get { return name; } set { name = value; } } } class Program { static void Main() { Person person = new Person(); person.Name = "John"; // Accessing private field via property Console.WriteLine(person.Name); } }
Explanation: Abstraction in C# refers to hiding the implementation details and exposing only the essential features of an object. It is achieved using abstract classes and interfaces, allowing you to define methods without providing the complete implementation.
// Example of abstraction in C# public abstract class Animal { public abstract void Speak(); // Abstract method } public class Dog : Animal { public override void Speak() // Implementing abstract method { Console.WriteLine("Dog barks"); } } class Program { static void Main() { Animal myDog = new Dog(); myDog.Speak(); // Dog barks } }
Explanation: Both interfaces and abstract classes allow you to define methods without implementation, but there are key differences:
- Abstract class: Can have both abstract methods (without implementation) and concrete methods (with implementation). A class can inherit only one abstract class.
- Interface: Can only have method signatures (no implementation), and a class can implement multiple interfaces.
// Example of abstract class and interface in C# public interface IAnimal { void Speak(); } public abstract class Animal { public abstract void Speak(); // Abstract method } public class Dog : Animal, IAnimal { public override void Speak() // Implementing abstract method { Console.WriteLine("Dog barks"); } } class Program { static void Main() { Dog dog = new Dog(); dog.Speak(); // Outputs: Dog barks } }
Explanation: Yes, a class can inherit multiple interfaces. C# allows a class to implement multiple interfaces, which helps achieve polymorphism and flexibility in code design.
// Example of multiple interfaces implementation public interface IAnimal { void Speak(); } public interface IFlyable { void Fly(); } public class Bird : IAnimal, IFlyable { public void Speak() { Console.WriteLine("Bird sings"); } public void Fly() { Console.WriteLine("Bird flies"); } } class Program { static void Main() { Bird bird = new Bird(); bird.Speak(); // Outputs: Bird sings bird.Fly(); // Outputs: Bird flies } }
Explanation:
- Method Overloading: Occurs when you define multiple methods with the same name but with different parameters (different number, type, or order of parameters).
- Method Overriding: Occurs when a derived class redefines a method in the base class to provide a specific implementation.
// Example of method overloading and overriding in C# public class Animal { public virtual void Speak() { Console.WriteLine("Animal speaks"); } public void Speak(string sound) { Console.WriteLine($"Animal makes a {sound} sound"); } } public class Dog : Animal { public override void Speak() // Overriding base method { Console.WriteLine("Dog barks"); } } class Program { static void Main() { Animal animal = new Animal(); animal.Speak(); // Outputs: Animal speaks animal.Speak("growl"); // Outputs: Animal makes a growl sound Dog dog = new Dog(); dog.Speak(); // Outputs: Dog barks } }
Explanation: A sealed class in C# cannot be inherited. It is used when you want to prevent further subclassing of a class. For example, a class representing a utility or final implementation might be sealed to prevent modification.
// Example of a sealed class in C# public sealed class FinalClass { public void DisplayMessage() { Console.WriteLine("This is a final class"); } } // Error: Cannot inherit from sealed class // public class DerivedClass : FinalClass {} // Compiler error class Program { static void Main() { FinalClass fc = new FinalClass(); fc.DisplayMessage(); // Outputs: This is a final class } }
Explanation: A static class cannot be instantiated. It can only contain static members (fields, methods, properties). Static classes are used for utility or helper functions that do not require an instance of the class.
// Example of a static class in C# public static class MathUtility { public static int Add(int a, int b) => a + b; public static int Multiply(int a, int b) => a * b; } class Program { static void Main() { Console.WriteLine(MathUtility.Add(5, 3)); // Outputs: 8 Console.WriteLine(MathUtility.Multiply(4, 2)); // Outputs: 8 } }
Explanation: Delegates in C# are type-safe function pointers that can reference methods with a specific signature. They allow methods to be passed as parameters, which helps in event handling and callback scenarios.
// Example of delegate in C# public delegate void GreetDelegate(string name); public class Greeter { public void Greet(string name) { Console.WriteLine($"Hello, {name}!"); } } class Program { static void Main() { Greeter greeter = new Greeter(); GreetDelegate greetDelegate = new GreetDelegate(greeter.Greet); greetDelegate("John"); // Outputs: Hello, John! } }
Explanation: Events in C# are used to provide notifications. They are based on delegates and allow a class to broadcast messages to other classes. The event keyword is used to declare an event in C#.
// Example of event in C# public class Alarm { public event EventHandler AlarmRang; public void Ring() { Console.WriteLine("Alarm is ringing!"); AlarmRang?.Invoke(this, EventArgs.Empty); // Raise event } } class Program { static void Main() { Alarm alarm = new Alarm(); alarm.AlarmRang += (sender, e) => { Console.WriteLine("Alarm received by listener!"); }; alarm.Ring(); // Outputs: Alarm is ringing! Alarm received by listener! } }
Explanation: Generics in C# allow you to define classes, methods, and data structures with a placeholder for the data type. They provide type safety and reduce the need for casting.
// Example of generics in C# public class Box{ private T _item; public Box(T item) { _item = item; } public T GetItem() { return _item; } } class Program { static void Main() { Box intBox = new Box (5); Console.WriteLine(intBox.GetItem()); // Outputs: 5 Box strBox = new Box ("Hello"); Console.WriteLine(strBox.GetItem()); // Outputs: Hello } }
Explanation: LINQ (Language Integrated Query) is a set of methods that allows querying collections like arrays, lists, and databases in a concise and readable manner. It integrates query capabilities into C#.
// Example of LINQ in C# using System; using System.Linq; class Program { static void Main() { int[] numbers = { 1, 2, 3, 4, 5 }; var evenNumbers = from num in numbers where num % 2 == 0 select num; foreach (var num in evenNumbers) { Console.WriteLine(num); // Outputs: 2, 4 } } }
Explanation: An extension method allows you to add new functionality to existing types without modifying their source code. They are defined as static methods in static classes but can be called as if they were instance methods on the type.
// Example of extension method in C# public static class StringExtensions { public static bool IsPalindrome(this string str) { var reversed = new string(str.Reverse().ToArray()); return str.Equals(reversed, StringComparison.OrdinalIgnoreCase); } } class Program { static void Main() { string word = "madam"; Console.WriteLine(word.IsPalindrome()); // Outputs: True } }
Explanation: A nullable type allows value types (like int, float) to be assigned a null value. It is useful for database operations where a field can be empty.
// Example of nullable type in C# public class Product { public int? Price { get; set; } // Nullable int } class Program { static void Main() { Product product = new Product(); product.Price = null; Console.WriteLine(product.Price.HasValue ? product.Price.ToString() : "No price set"); // Outputs: No price set } }
Explanation: Both "ref" and "out" allow passing parameters by reference, but there are key differences:
- ref: The parameter must be initialized before passing it to the method.
- out: The parameter does not need to be initialized, and it must be assigned a value before the method returns.
// Example of ref and out parameters public class Calculator { public void Add(ref int a, out int b) { a = a + 5; b = 10; } } class Program { static void Main() { int x = 5; int y; Calculator calculator = new Calculator(); calculator.Add(ref x, out y); Console.WriteLine($"x: {x}, y: {y}"); // Outputs: x: 10, y: 10 } }
Explanation: Async and await are keywords that help make asynchronous programming easier. They allow you to write code that performs non-blocking operations (like web requests or file reading) without blocking the main thread.
// Example of async and await in C# using System; using System.Threading.Tasks; class Program { static async Task Main() { Console.WriteLine("Starting async task..."); await Task.Delay(2000); // Simulates an asynchronous operation Console.WriteLine("Task completed!"); } }
Explanation: A task in C# represents an asynchronous operation. It is a wrapper for a unit of work that can be executed asynchronously, and it's part of the Task Parallel Library (TPL) in .NET.
// Example of Task in C# using System; using System.Threading.Tasks; class Program { static async Task Main() { Task task = Task.Run(() => { Console.WriteLine("Task is running!"); }); await task; } }
Explanation: Both Task and Thread represent units of work, but:
- Thread: Represents a separate thread of execution in the program.
- Task: Represents an asynchronous operation and is more lightweight and easier to manage compared to threads.
// Example of Task vs Thread using System; using System.Threading; using System.Threading.Tasks; class Program { static void Main() { Task.Run(() => { Console.WriteLine("Task is running!"); }); // Task example Thread thread = new Thread(() => { Console.WriteLine("Thread is running!"); }); thread.Start(); // Thread example } }
Explanation: Dependency Injection (DI) is a design pattern used to implement Inversion of Control (IoC), where a class's dependencies are provided externally rather than being created internally. It promotes loose coupling and improves testability.
// Example of Dependency Injection in C# public interface IMessageService { void SendMessage(string message); } public class EmailService : IMessageService { public void SendMessage(string message) { Console.WriteLine($"Sending email: {message}"); } } public class Notification { private readonly IMessageService _messageService; // Dependency Injection through constructor public Notification(IMessageService messageService) { _messageService = messageService; } public void Notify(string message) { _messageService.SendMessage(message); } } class Program { static void Main() { IMessageService emailService = new EmailService(); Notification notification = new Notification(emailService); notification.Notify("Hello, Dependency Injection!"); } }
Explanation: An interface defines a contract for classes to implement, but it cannot contain any implementation. An abstract class can have both abstract methods (without implementation) and concrete methods (with implementation). A class can implement multiple interfaces but can only inherit one abstract class.
// Example of Interface vs Abstract Class in C# public interface IDriveable { void Drive(); } public abstract class Vehicle { public abstract void Start(); public void Stop() => Console.WriteLine("Vehicle stopped"); } public class Car : Vehicle, IDriveable { public override void Start() => Console.WriteLine("Car started"); public void Drive() => Console.WriteLine("Car is driving"); } class Program { static void Main() { Car car = new Car(); car.Start(); // Outputs: Car started car.Drive(); // Outputs: Car is driving car.Stop(); // Outputs: Vehicle stopped } }
Explanation: A stack is a collection that follows the Last In, First Out (LIFO) principle. The last element added is the first one to be removed. A queue follows the First In, First Out (FIFO) principle, where the first element added is the first to be removed.
// Example of Stack and Queue in C# using System; using System.Collections.Generic; class Program { static void Main() { Stackstack = new Stack (); stack.Push(1); // Stack: 1 stack.Push(2); // Stack: 2, 1 Console.WriteLine(stack.Pop()); // Outputs: 2 Queue queue = new Queue (); queue.Enqueue(1); // Queue: 1 queue.Enqueue(2); // Queue: 1, 2 Console.WriteLine(queue.Dequeue()); // Outputs: 1 } }
Explanation: A value type holds its data directly (e.g., int, float), and each instance has its own copy of the data. A reference type holds a reference to the memory location of the data (e.g., string, arrays, class), and multiple references can point to the same data.
// Example of Value Type vs Reference Type in C# int x = 10; // Value type int y = x; // y gets a copy of x's value y = 20; Console.WriteLine(x); // Outputs: 10 Console.WriteLine(y); // Outputs: 20 string str1 = "Hello"; // Reference type string str2 = str1; // str2 points to the same memory location as str1 str2 = "World"; Console.WriteLine(str1); // Outputs: Hello Console.WriteLine(str2); // Outputs: World
Explanation: A constructor is a special method that is automatically called when an object is created. It initializes the object's state. A method is a function that performs an action and is called explicitly during the object's lifetime.
// Example of Constructor vs Method in C# public class Person { public string Name { get; set; } // Constructor public Person(string name) { Name = name; } // Method public void Greet() { Console.WriteLine($"Hello, my name is {Name}"); } } class Program { static void Main() { Person person = new Person("John"); // Constructor called person.Greet(); // Method called } }
Explanation: Constructor overloading refers to defining multiple constructors in a class, each with a different number of parameters or types of parameters. It allows the creation of objects in various ways.
// Example of Constructor Overloading in C# public class Person { public string Name { get; set; } public int Age { get; set; } // Constructor 1 public Person(string name) { Name = name; } // Constructor 2 public Person(string name, int age) { Name = name; Age = age; } } class Program { static void Main() { Person person1 = new Person("John"); Person person2 = new Person("Alice", 30); } }
Explanation: Access modifiers define the accessibility of types and their members. Common access modifiers are:
- public: Accessible from anywhere.
- private: Accessible only within the same class.
- protected: Accessible within the same class and derived classes.
- internal: Accessible within the same assembly.
- protected internal: Accessible within the same assembly or derived classes.
// Example of Access Modifiers in C# public class Car { public string Make { get; set; } private int year; // Private field public Car(string make, int year) { Make = make; this.year = year; } public void DisplayYear() { Console.WriteLine($"Year: {year}"); } } class Program { static void Main() { Car car = new Car("Tesla", 2022); Console.WriteLine(car.Make); // Public property car.DisplayYear(); // Private field accessed through method } }
Explanation: Boxing is the process of converting a value type to a reference type (object). Unboxing is the process of converting an object back to a value type.
// Example of Boxing and Unboxing in C# int num = 42; object obj = num; // Boxing int unboxedNum = (int)obj; // Unboxing Console.WriteLine(unboxedNum); // Outputs: 42
Explanation: A static class is a class that cannot be instantiated. It can only contain static members (fields, methods, properties). A static class is used for utility functions and for grouping methods that do not require object instantiation.
// Example of Static Class in C# public static class MathHelper { public static int Add(int a, int b) => a + b; } class Program { static void Main() { Console.WriteLine(MathHelper.Add(5, 3)); // Outputs: 8 } }
Explanation: A shallow copy copies the object, but references to objects inside are not copied; they refer to the original objects. A deep copy creates copies of all objects inside the original object, so no references are shared.
// Example of Shallow and Deep Copy in C# using System; using System.Collections.Generic; using System.Linq; class Program { static void Main() { ListoriginalList = new List { 1, 2, 3 }; List shallowCopy = originalList; // Shallow copy List deepCopy = originalList.ToList(); // Deep copy shallowCopy[0] = 99; Console.WriteLine(originalList[0]); // Outputs: 99 (shallow copy refers to same list) Console.WriteLine(deepCopy[0]); // Outputs: 1 (deep copy is independent) } }
Explanation: A delegate is a type-safe function pointer in C#. It allows methods to be passed as parameters and provides a way to invoke methods indirectly.
// Example of Delegate in C# public delegate void GreetDelegate(string message); class Program { static void Main() { GreetDelegate greet = Greet; greet("Hello, Delegates!"); // Outputs: Hello, Delegates! } static void Greet(string message) { Console.WriteLine(message); } }
Explanation: The using keyword has two main purposes in C#:
- To import namespaces so their types can be used in the code without requiring fully qualified names.
- To ensure that resources are disposed of correctly by automatically calling the `Dispose` method of objects when they go out of scope (used in the `using` statement).
// Example of using `using` in C# using System; class Program { static void Main() { using (var writer = new System.IO.StreamWriter("output.txt")) { writer.WriteLine("Hello, Using Keyword!"); } } }
Explanation: A property is a member of a class that provides a mechanism to read, write, or compute the values of private fields. It is often used instead of public fields to control access to the data.
// Example of Property in C# public class Person { private string name; // Property public string Name { get { return name; } set { name = value; } } } class Program { static void Main() { Person person = new Person(); person.Name = "John"; // Set value using property Console.WriteLine(person.Name); // Get value using property } }
Explanation: A lambda expression is a concise way to represent an anonymous function (method) using a syntax that is more readable. Lambda expressions are often used with LINQ queries and delegates.
// Example of Lambda Expression in C# using System; using System.Linq; class Program { static void Main() { var numbers = new int[] { 1, 2, 3, 4, 5 }; var evenNumbers = numbers.Where(n => n % 2 == 0).ToList(); // Lambda expression to filter even numbers foreach (var num in evenNumbers) { Console.WriteLine(num); // Outputs: 2, 4 } } }
Explanation: The == operator compares reference types by reference (memory location) and value types by value. The Equals() method compares the values of objects and can be overridden in custom types to provide custom comparison logic.
// Example of `==` vs `Equals()` in C# string str1 = "Hello"; string str2 = "Hello"; Console.WriteLine(str1 == str2); // Outputs: True (compares by value for reference types) Console.WriteLine(str1.Equals(str2)); // Outputs: True (compares by value for reference types) object obj1 = new object(); object obj2 = new object(); Console.WriteLine(obj1 == obj2); // Outputs: False (compares by reference) Console.WriteLine(obj1.Equals(obj2)); // Outputs: False (compares by reference)
Explanation: The async keyword is used to mark a method as asynchronous, allowing it to run asynchronously without blocking the main thread. The await keyword is used inside an async method to call a task asynchronously and wait for its result without blocking the thread.
// Example of `async` and `await` in C# using System; using System.Threading.Tasks; class Program { static async Task Main() { await DoWorkAsync(); // Calling async method Console.WriteLine("Work completed"); } static async Task DoWorkAsync() { await Task.Delay(2000); // Simulating async work Console.WriteLine("Work is done"); } }
Explanation: A Task is a higher-level abstraction that manages asynchronous operations and is part of the Task Parallel Library (TPL). A Thread is a low-level OS-level construct that allows parallel execution of code. Tasks provide better performance and scalability than raw threads.
// Example of Task vs Thread in C# using System; using System.Threading; using System.Threading.Tasks; class Program { static void Main() { // Using Task Task.Run(() => Console.WriteLine("Task running")); // Using Thread Thread thread = new Thread(() => Console.WriteLine("Thread running")); thread.Start(); } }
Explanation: Both ref and out are used to pass arguments by reference, but:
- ref: The argument must be initialized before being passed to the method.
- out: The argument does not need to be initialized before being passed to the method, but it must be assigned a value within the method.
// Example of `ref` vs `out` in C# using System; class Program { static void Main() { int refValue = 10; ModifyRef(ref refValue); // Pass by reference Console.WriteLine(refValue); // Outputs: 20 int outValue; ModifyOut(out outValue); // Pass by out Console.WriteLine(outValue); // Outputs: 30 } static void ModifyRef(ref int x) { x = 20; } static void ModifyOut(out int x) { x = 30; } }
Explanation: A try-catch block is used to handle exceptions in C#. The try block contains the code that might throw an exception, and the catch block contains the code to handle the exception if it occurs.
// Example of `try-catch` block in C# using System; class Program { static void Main() { try { int result = 10 / 0; // This will throw an exception } catch (DivideByZeroException ex) { Console.WriteLine("Error: " + ex.Message); // Handle the exception } } }
Explanation: Polymorphism is the ability of an object to take on many forms. It allows methods to be used interchangeably, even if they are defined in different classes. In C#, polymorphism is achieved through method overriding (runtime polymorphism) and method overloading (compile-time polymorphism).
// Example of Polymorphism in C# using System; class Animal { public virtual void Speak() { Console.WriteLine("Animal speaks"); } } class Dog : Animal { public override void Speak() { Console.WriteLine("Dog barks"); } } class Program { static void Main() { Animal myDog = new Dog(); myDog.Speak(); // Outputs: Dog barks } }
0 Comments