Written by 13:31 Basics of C#, Languages & Coding • 3 Comments

Tricky Questions about C#

Some questions may seem too basic, but they still contain tiny tricks. Sometimes even a simple question may nail to the wall. These questions will be useful to all who study the language.

So, let’s start!

1. What will be the result of execution of the following code?

   static String str;
   static DateTime time;

        static void Main(string[] args)
        {
            Console.WriteLine(str == null ? "str == null" : str);
            Console.WriteLine(time == null ? "time == null" : time.ToString());
            Console.ReadLine();
        }

[expand title =”Answer”]

str == null

1/1/0001 12:00:00 AM

Both variables are not initialized, but a string is a reference type (to be more specific, it is an immutable type, which means reference type with the semantics of the value type). DateTime is a value type. The default value of the initialized DateTime type is 1/1/0001 12:00:00 AM.
[/expand]

2. Let’s play with inheritance. What will be outputted?

        class A
        {
            public void abc(int q)
            {
                Console.WriteLine("abc from A");
            }
        }

        class B : A
        {
            public void abc(double p)
            {
                Console.WriteLine("abc from B");
            }
        }

        static void Main(string[] args)
        {
            int i = 5;
            B b = new B();
            b.abc(i);
            Console.ReadLine();
        }

[expand title =”Answer”]

abc from B.

[/expand]

3. A similar question. What will be the result?

        class P
        { }
        class Q : P
        { }

        class A
        {
            public void abc(Q q)
            {
                Console.WriteLine("abc from A");
            }
        }

        class B : A
        {
            public void abc(P p)
            {
                Console.WriteLine("abc from B");
            }
        }

        static void Main(string[] args)
        {
            B b = new B();
            b.abc(new Q());
            Console.ReadLine();
        } 

[expand title =”Answer”]
abc from B.

Here everything is more obvious than in the previous question.

[/expand]

4. A typical polymorphism understanding swindle. The main thing is not to forget and overlook anything. What will be the result of execution of the following code?

    class Program
    {
        static void Main(string[] args)
        {
            MyClassB b = new MyClassB();
            MyClassA a = b;
            a.abc();
            Console.ReadLine();
        }
    }

    class MyClassA
    {
        public MyClassA()
        {
            Console.WriteLine("constructor A");
        }

        public void abc()
        {
            Console.WriteLine("A");
        }
    }

    class MyClassB:MyClassA
    {
        public MyClassB()
        {
            Console.WriteLine("constructor B");
        }

        public void abc()
        {
            Console.WriteLine("B");
        }
    }

[expand title =”Answer”]

constructor A
constructor B
A

During initialization of the B class, the constructor of the A class will be executed by default, then constructor of the B class. After assignment of the b value to a type variable of the A class, we will get an instance of the B class in it. One would think that abc() from the B class should be called, but since there is no specification of any predicate of the abc method in the B class, it hides abc from the A class. The example is not quite correct and abc() in the B class will be underlined, since the new predicate is required.[/expand]

5. I have the following class:

        public class Point
        {
            public int X { get; set; }
            public int Y { get; set; }
            public Point(int xPos, int yPos)
            {
                X = xPos;
                Y = yPos;
            }
        }

Also, I have 3 instances of the class. Will the following initialization of the third instance work? If it won’t, what should be done?

            Point ptOne = new Point(15, 20);
            Point ptTwo = new Point(40, 50);
            Point ptThree = ptOne + ptTwo;

[expand title =”Answer”]
Of course, the example will not work. To make this code work, we need to add the addition operator overloading to the Point class. For example, the following one:

            public static Point operator +(Point p1, Point p2)
            {
                return new Point(p1.X + p2.X, p1.Y + p2.Y);
            }

[/expand]

6. What will be the execution result of the following query?

        string result;

        private async void btnStart_Click(object sender, RoutedEventArgs e)
        {
            SaySomething();
            txtSomeTextBlock.Text = result;
        }

        async System.Threading.Tasks.Task<string> SaySomething()
        {
            await System.Threading.Tasks.Task.Delay(1000);

            result = "Hello world!";
            return result;
        }

[expand title =”Answer”]
An empty string will be outputted instead of ‘Hello world!’. The SaySomething() task was called without await, and that is why, SaySomethinf is executed synchronously till the first await, i.e. till the first string:

await System.Threading.Tasks.Task.Delay(1000);

After this, execution is returned to btnStartClick. If we use await during the call of SaySomething(), the result will be expected, – ‘Hello world’ will be outputted.[/expand]

7. A must-know question. What will be the execution result of the following query?

    delegate void SomeMethod();

        static void Main(string[] args)
        {
            List<SomeMethod> delList = new List<SomeMethod>();
            for (int i = 0; i < 10; i++)
            {
                delList.Add(delegate { Console.WriteLine(i); });
            }

            foreach (var del in delList)
            {
                del();
            }
        }

[expand title =”Answer”]

The program will output the number 10 times.

The delegate was added 10 times. The reference to the i variable was taken. The reference, not the value. That is why, when calling a delegate, the last value of the i variable is taken. It is a typical example of closure.[/expand]

8. What will be outputted with the following code?

        static bool SomeMethod1()
        {
            Console.WriteLine("Method 1");
            return false;
        }

       static bool SomeMethod2()
        {
            Console.WriteLine("Method 2");
            return true;
        }
        static void Main(string[] args)
        {
            if (SomeMethod1() & SomeMethod2())
            {
                Console.WriteLine("the if block has was executed");
            }
        }

[expand title =”Answer”]

Method 1

Method 2

The if block won’t be executed since SomeMethod1 returns false. But, since the & logical operator is used, the second condition, SomeMethod2, will be also checked. If a more conventional && operator was used, only the value of the first method would be checked.[/expand]

9. One more simple question. What will be the output of the following code?

            double e = 2.718281828459045;
            object o = e; // box
            int ee = (int)o;

[expand title =”Answer”]

This code won’t work and will throw an exception in the last string. However, the next casting (in other words, explicit conversion) of the error should not call the error, but just looses fractional part of a number.But during unboxing, the object is checked for the value of the requested type. And the value is copied into the variable only after the first check. And the next one will make unboxing without the error:

            double e = 2.718281828459045;
            int ee = (int)e;

But during unboxing, the object is checked for the value of the requested type. And the value is copied into the variable only after the first check.

And the next one will make unboxing without the error:

            int ee = (int)(double)o;

The following code will firtsly execute upcast of the o object to the dynamic tye, and then will make casting, not unboxing:

            int ee = (int)(o as dynamic);

However, it is similar to the following code:

     int ee = (int)(o is dynamic ? (dynamic)o : (dynamic)null);

As a result, it will be identical to the first example:

            int ee = (int)(dynamic)o;

Although, it seemed to be a new trick.[/expand]

10. What will happen after the execution of the following code?

            float q = float.MaxValue;
            float w = float.MaxValue;

            checked
            {
                float a = q * w;
                Console.WriteLine(a.ToString());
            }

[expand title =”Answer”]

Infinity will be outputted.

Float and double are not integral types. That is why, if we use checked, overflow does not take place. Though, if we used int, byte, short or long, an expected error would occur. Unchecked will not work with not built-in types as well. For example, the following code:

            decimal x = decimal.MaxValue;
            decimal y = decimal.MaxValue;

            unchecked
            {
                decimal z = x * y;
                Console.WriteLine(z.ToString());
            }

will trhow System.OverflowException.[/expand]

11. Let’s play with the decimal type. Will something be outputted? If it will, what will it be?

            int x = 5;
            decimal y = x / 12;
            Console.WriteLine(y.ToString());

[expand title =”Answer”]

This example will output 0 because x has not been reduced to the decimal type. Since x is of the integer type, when 5 is divided by 12, the result is a number less than 1, that is, an integral zero. The correct result can be obtained with the following line:

   decimal y = (decimal)x / 12;

[/expand]

12. What is the output of the following code?

            double d=5.15;
            d = d / 0;

            float f = 5.15f;
            f = f / 0;

            decimal dc = 5.12m;
            dc = dc / 0;

[expand title =”Answer”]

Division of the double and float types by 0 will return infinity, while decimal will throw System.DivideByZeroException.

Just in case, a few words about about the diffs between decimal and float:

  • decimal (128-bit data type with precision of 28-29 digits) is used for finacial calculations which require high precision and no errors in rounding;
  • double ( a 54-bit type with precision accuracy to 15-16 digits) is a basic type for storing floating-point values. Used in most cases (except financial);
  • float (32-bit data type with precision of 7 digits) – a type with the lowest precision and range, but with the highest performance. Rounding errors are possible. Used for heavy-loaded calculations.[/expand]

    13. Consider, we have the following method:

    int SomeMethod(int x, int y)
        {
            return (x - y) * (x + y);
        }

    Can we call it in the following way?

    SomeMethod(y:17, x:21)

    [expand title =”Answer”]

    Yes, we can. We can also call it in a different way:

    SomeMethod(11, y:27)

    But we can’t call it in the following way:

    SomeMethod(x:12, 11)

    UPDATE: As from C# 7.2, making such call might become impossible.[/expand]

    14. What is the output of the following code?

            static void Main(string[] args)
            {
                int someInt;
                SomeMethod2(out someInt);
                Console.WriteLine(someInt);
    
                SomeMethod1(ref someInt);
                Console.WriteLine(someInt);
    
                SomeMethod(someInt);
                Console.WriteLine(someInt);
    
                Console.ReadLine();
            }
    
    
            static void SomeMethod(int value)
            {
                value = 0;
            }
            static void SomeMethod1(ref int value)
            {
                value = 1;
            }
            static void SomeMethod2(out int value)
            {
                value = 2;
            }
    

    [expand title =”Answer”]

    Nothing bad will happen. The following will be outputted:

    2
    1
    1

    Since we call SomeMethod2 with the out keyword first, someInt may be passed without initialization. If we used SomeMethod or SomeMethod1, the compilation error would occur.

    Since SomeMethod does not contain the ref or out keyword in the parameter, the value is passed by value, not by reference, which means that someInt will not be changed.

    The ref and out keywords mean that the values are passed by reference. But in the second case, a value must be assigned to the parameter in the method. In our example, in the SomeMethod2 method, a value must be assigned to the value parameter.[/expand]

    15. Will the following code work?

            static void Main(string[] args)
            {
                goto lalala;
                int i = 5;
                { Console.WriteLine(i); }
                lalala:
                Console.WriteLine("Bye, cruel world! (=");
                Console.ReadLine();
            }

    [expand title =”Answer”]

    Yes, but it looks strange. Only Bye, cruel world! will be outputted. Inside the method, we can declare inclusive local region between curly braces. Variables from this region will be unavailable outside of it. That is, the following code will not Fbe compiled:

            static void Main(string[] args)
            {
                { int i = 10; }
                Console.WriteLine(i);
            }

    Strange enough, goto is still not supported in C#. Though, it is not required much.[/expand]

    16. What will be outputted?

    string hello = "hello";
            string helloWorld = "hello world";
            string helloWorld2 = "hello world";
            string helloWorld3 = hello + " world";
    
            Console.WriteLine(helloWorld == helloWorld2);
            Console.WriteLine(object.ReferenceEquals(helloWorld, helloWorld2));
            Console.WriteLine(object.ReferenceEquals(helloWorld, helloWorld3));
            Console.ReadLine();

    [expand title =”Answer”]

    True, True, False will be outputted.

    It is a typical example of string interning. Situations when strings storing the same value represent one object in memory. This mechanizm allows using memory more sparingly.[/expand]

    17. Can pointers be used in C# as in C++?

    [expand title =”Answer”]

    Yes, they can be used inside the method declared with the unsafe modifier or within the unsafe block.

    unsafe {  
        int a = 15; 
        *b = &a;
        Console.WriteLine(*b); 
              }

    Do not forget to specify ‘Allow unsafe code’ in the project properties.[/expand]

    18. What are verbatim strings?

    [expand title =”Answer”]

    Everybody knows what these strings are and constantly uses them, but not everyone knows their name. Verbatim strings are strings that start with the @ symbol in which the escape sequences are not processed.[/expand]

    See Also:

    Tags: , Last modified: September 23, 2021
Close