DEV Community

Cover image for 11 Most Asked C# Questions
KiranPoudel98 for Truemark Technology

Posted on • Originally published at thedevpost.com

11 Most Asked C# Questions

C# is a general-purpose and object-oriented programming language developed by Microsoft. It is mostly used for developing desktop and web applications. So, today we will be talking about the 11 frequently asked questions about C# programming language.

11 Frequently Asked C# Questions

1. What is the difference between String and string in C#?

Answer:

string is an alias in C# for System.String.
So technically, there is no difference. It’s like int vs. System.Int32.

As far as guidelines, it’s generally recommended to use string any time you’re referring to an object.

e.g.

string place = "world";
Enter fullscreen mode Exit fullscreen mode

Likewise, it’s generally recommended to use String if you need to refer specifically to the class.

e.g.

string greet = String.Format("Hello {0}!", place);
Enter fullscreen mode Exit fullscreen mode

This is the style that Microsoft tends to use in their examples.

It appears that the guidance in this area may have changed, as StyleCop now enforces the use of the C# specific aliases.

Alternative Answer:

string is an alias for System.String. They compile to the same code, so at execution time there is no difference whatsoever. This is just one of the aliases in C#. The complete list is:

object:  System.Object
string:  System.String
bool:    System.Boolean
byte:    System.Byte
sbyte:   System.SByte
short:   System.Int16
ushort:  System.UInt16
int:     System.Int32
uint:    System.UInt32
long:    System.Int64
ulong:   System.UInt64
float:   System.Single
double:  System.Double
decimal: System.Decimal
char:    System.Char
Enter fullscreen mode Exit fullscreen mode

Apart from string and object, the aliases are all to value types. decimal is a value type, but not a primitive type in the CLR. The only primitive type which doesn’t have an alias is System.IntPtr.

In the spec, the value type aliases are known as “simple types”. Literals can be used for constant values of every simple type; no other value types have literal forms available. (Compare this with VB, which allows DateTime literals, and has an alias for it too.)

There is one circumstance in which you have to use the aliases: when explicitly specifying an enum’s underlying type. For instance:

public enum Foo : UInt32 {} // Invalid
public enum Bar : uint   {} // Valid
Enter fullscreen mode Exit fullscreen mode

That’s just a matter of the way the spec defines enum declarations – the part after the colon has to be the integral-type production, which is one token of sbyte, byte, short, ushort, int, uint, long, ulong, char… as opposed to a type production as used by variable declarations for example. It doesn’t indicate any other difference.

Finally, when it comes to which to use: the CLR type is for any APIs. It really doesn’t matter too much which you use in terms of implementation – consistency among your team is nice, but no-one else is going to care. On the other hand, it’s genuinely important that if you refer to a type in an API, you do so in a language-neutral way. A method called ReadInt32 is unambiguous, whereas a method called ReadInt requires interpretation. The caller could be using a language that defines an int alias for Int16, for example. The .NET framework designers have followed this pattern, good examples being in the BitConverter, BinaryReader, and Convert classes.

2. How to cast an int to enum?

Answer:

From a string:

YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString);

// The foo.ToString().Contains(",") check is necessary for enumerations marked with an [Flags] attribute
if (!Enum.IsDefined(typeof(YourEnum), foo) && !foo.ToString().Contains(","))
{
    throw new InvalidOperationException($"{yourString} is not an underlying value of the YourEnum enumeration.")
}
Enter fullscreen mode Exit fullscreen mode

From an int:

YourEnum foo = (YourEnum)yourInt;
Enter fullscreen mode Exit fullscreen mode

From the number also you can

YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum) , yourInt);
Enter fullscreen mode Exit fullscreen mode

Alternative Answer:

Just cast it:

MyEnum e = (MyEnum)3;
Enter fullscreen mode Exit fullscreen mode

You can check if it’s in range using Enum.IsDefined:

if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }
Enter fullscreen mode Exit fullscreen mode

3. What is the best way to iterate over a dictionary?

Answer:

The best way to do is

foreach(KeyValuePair<string, string> entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}
Enter fullscreen mode Exit fullscreen mode

Alternative Answer:

If you are trying to use a generic Dictionary in C# like you would use an associative array in another language:

foreach(var item in myDictionary)
{
  foo(item.Key);
  bar(item.Value);
}
Enter fullscreen mode Exit fullscreen mode

Or, if you only need to iterate over the collection of keys, use

foreach(var item in myDictionary.Keys)
{
  foo(item);
}
Enter fullscreen mode Exit fullscreen mode

And lastly, if you’re only interested in the values:

foreach(var item in myDictionary.Values)
{
  foo(item);
}
Enter fullscreen mode Exit fullscreen mode

(Take note that the var keyword is an optional C# 3.0 and above feature, you could also use the exact type of your keys/values here)

4. What are the correct version numbers for C#?

Answer:

C# language version history:

These are the versions of C# known about at the time of this writing:

5. How to clone or deep copy an object so that the cloned object can be modified without any changes being reflected in the original object?

Answer:

Whilst the standard practice is to implement the ICloneable interface, here’s a nice deep clone object copier found on The Code Project and incorporated it.

As mentioned, it does require your objects to be serializable.

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

/// <summary>
/// Reference Article http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx
/// Provides a method for performing a deep copy of an object.
/// Binary Serialization is used to perform the copy.
/// </summary>
public static class ObjectCopier
{
    /// <summary>
    /// Perform a deep Copy of the object.
    /// </summary>
    /// <typeparam name="T">The type of object being copied.</typeparam>
    /// <param name="source">The object instance to copy.</param>
    /// <returns>The copied object.</returns>
    public static T Clone<T>(T source)
    {
        if (!typeof(T).IsSerializable)
        {
            throw new ArgumentException("The type must be serializable.", nameof(source));
        }

        // Don't serialize a null object, simply return the default for that object
        if (Object.ReferenceEquals(source, null))
        {
            return default(T);
        }

        IFormatter formatter = new BinaryFormatter();
        Stream stream = new MemoryStream();
        using (stream)
        {
            formatter.Serialize(stream, source);
            stream.Seek(0, SeekOrigin.Begin);
            return (T)formatter.Deserialize(stream);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

The idea is that it serializes your object and then deserializes it into a fresh object. The benefit is that you don’t have to concern yourself about cloning everything when an object gets too complex.

And with the use of extension methods (also from the originally referenced source):

In case you prefer to use the new extension methods of C# 3.0, change the method to have the following signature:

public static T Clone<T>(this T source)
{
   //...
}
Enter fullscreen mode Exit fullscreen mode

Now the method call simply becomes objectBeingCloned.Clone();.

You can also use JSON to do this, it should be lighter, and avoids the overhead of [Serializable] tags.

/// <summary>
/// Perform a deep Copy of the object, using Json as a serialisation method. NOTE: Private members are not cloned using this method.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T CloneJson<T>(this T source)
{            
    // Don't serialize a null object, simply return the default for that object
    if (Object.ReferenceEquals(source, null))
    {
        return default(T);
    }

    // initialize inner objects individually
    // for example in default constructor some list property initialized with some values,
    // but in 'source' these items are cleaned -
    // without ObjectCreationHandling.Replace default constructor values will be added to result
    var deserializeSettings = new JsonSerializerSettings {ObjectCreationHandling = ObjectCreationHandling.Replace};

    return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source), deserializeSettings);
}
Enter fullscreen mode Exit fullscreen mode

Alternative Answer:

If your object is out of the box JSON serializable then this method will do the trick. This requires no modification or implementation of interfaces on the cloned class, just a JSON serializer like JSON.NET.

public static T Clone<T>(T source)
{
    var serialized = JsonConvert.SerializeObject(source);
    return JsonConvert.DeserializeObject<T>(serialized);
}
Enter fullscreen mode Exit fullscreen mode

Also, you can use this extension method

public static class SystemExtension
{
    public static T Clone<T>(this T source)
    {
        var serialized = JsonConvert.SerializeObject(source);
        return JsonConvert.DeserializeObject<T>(serialized);
    }
}
Enter fullscreen mode Exit fullscreen mode

6. How to get a consistent byte representation of strings in C# without manually specifying an encoding?

Answer:

You can just do this:

static byte[] GetBytes(string str)
{
    byte[] bytes = new byte[str.Length * sizeof(char)];
    System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
    return bytes;
}

// Do NOT use on arbitrary bytes; only use on GetBytes's output on the SAME system
static string GetString(byte[] bytes)
{
    char[] chars = new char[bytes.Length / sizeof(char)];
    System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
    return new string(chars);
}
Enter fullscreen mode Exit fullscreen mode

Alternative Answer:

It also depends on the encoding of your string (ASCII, UTF-8, …).

For example:

byte[] b1 = System.Text.Encoding.UTF8.GetBytes (myString);
byte[] b2 = System.Text.Encoding.ASCII.GetBytes (myString);
Enter fullscreen mode Exit fullscreen mode

A small sample of why encoding matters:

string pi = "\u03a0";
byte[] ascii = System.Text.Encoding.ASCII.GetBytes (pi);
byte[] utf8 = System.Text.Encoding.UTF8.GetBytes (pi);

Console.WriteLine (ascii.Length); //Will print 1
Console.WriteLine (utf8.Length); //Will print 2
Console.WriteLine (System.Text.Encoding.ASCII.GetString (ascii)); //Will print '?'
Enter fullscreen mode Exit fullscreen mode

ASCII simply isn’t equipped to deal with special characters.

Internally, the .NET framework uses UTF-16 to represent strings, so if you simply want to get the exact bytes that .NET uses, use System.Text.Encoding.Unicode.GetBytes (...).

See Character Encoding in the .NET Framework (MSDN) for more information.

7. Should ‘using’ directives be inside or outside the namespace?

Answer:

There is actually a (subtle) difference between the two. Imagine you have the following code in File1.cs:

// File1.cs
using System;
namespace Outer.Inner
{
    class Foo
    {
        static void Bar()
        {
            double d = Math.PI;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Now imagine that someone adds another file (File2.cs) to the project that looks like this:

// File2.cs
namespace Outer
{
    class Math
    {
    }
}
Enter fullscreen mode Exit fullscreen mode

The compiler searches Outer before looking at those using directives outside the namespace, so it finds Outer.Math instead of System.Math. Unfortunately (or perhaps fortunately?), Outer.Math has no PI member, so File1 is now broken.

This changes if you put the using inside your namespace declaration, as follows:

// File1b.cs
namespace Outer.Inner
{
    using System;
    class Foo
    {
        static void Bar()
        {
            double d = Math.PI;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Now the compiler searches System before searching Outer, finds System.Math, and all is well.

Some would argue that Math might be a bad name for a user-defined class since there’s already one in System; the point here is just that there is a difference, and it affects the maintainability of your code.

It’s also interesting to note what happens if Foo is in the namespace Outer, rather than Outer.Inner. In that case, adding Outer.Math in File2 breaks File1 regardless of where the using goes. This implies that the compiler searches the innermost enclosing namespace before it looks at any using directive.

8. How to generate a random int number?

Answer:

The Random class is used to create random numbers. (Pseudo-random that is of course.).

Example:

Random rnd = new Random();
int month  = rnd.Next(1, 13);  // creates a number between 1 and 12
int dice   = rnd.Next(1, 7);   // creates a number between 1 and 6
int card   = rnd.Next(52);     // creates a number between 0 and 51
Enter fullscreen mode Exit fullscreen mode

If you are going to create more than one random number, you should keep the Random instance and reuse it. If you create new instances too close in time, they will produce the same series of random numbers as the random generator is seeded from the system clock.

Alternative Answer:

Every time you do new Random() it is initialized . This means that in a tight loop you get the same value lots of times. You should keep a single Random instance and keep using Next on the same instance.

//Function to get random number
private static readonly Random getrandom = new Random();

public static int GetRandomNumber(int min, int max)
{
    lock(getrandom) // synchronize
    {
        return getrandom.Next(min, max);
    }
}
Enter fullscreen mode Exit fullscreen mode

9. How to create an Excel (.XLS and .XLSX) file in C# without installing Microsoft Office?

Answer:

You can use a library called ExcelLibrary. It’s a free, open-source library posted on Google Code: ExcelLibrary

It will not write to the new .xlsx format yet, but they are working on adding that functionality in.

It’s very simple, small, and easy to use. Plus it has a DataSetHelper that lets you use DataSets and DataTables to easily work with Excel data.

ExcelLibrary seems to still only work for the older Excel format (.xls files), but maybe adding support in the future for newer 2007/2010 formats.

You can also use EPPlus, which works only for Excel 2007/2010 format files (.xlsx files). There’s also NPOI which works with both.

There are a few known bugs with each library. In all, EPPlus seems to be the best choice as time goes on. It seems to be more actively updated and documented as well.

Also, EPPlus has support for Pivot Tables and ExcelLibrary may have some support (Pivot table issue in ExcelLibrary)

Here are a couple of links for quick reference:
ExcelLibraryGNU Lesser GPL
EPPlus – GNU Lesser General Public License (LGPL)
NPOI – Apache License

Here some example code for ExcelLibrary:

Here is an example of taking data from a database and creating a workbook from it. Note that the ExcelLibrary code is the single line at the bottom:

//Create the data set and table
DataSet ds = new DataSet("New_DataSet");
DataTable dt = new DataTable("New_DataTable");

//Set the locale for each
ds.Locale = System.Threading.Thread.CurrentThread.CurrentCulture;
dt.Locale = System.Threading.Thread.CurrentThread.CurrentCulture;

//Open a DB connection (in this example with OleDB)
OleDbConnection con = new OleDbConnection(dbConnectionString);
con.Open();

//Create a query and fill the data table with the data from the DB
string sql = "SELECT Whatever FROM MyDBTable;";
OleDbCommand cmd = new OleDbCommand(sql, con);
OleDbDataAdapter adptr = new OleDbDataAdapter();

adptr.SelectCommand = cmd;
adptr.Fill(dt);
con.Close();

//Add the table to the data set
ds.Tables.Add(dt);

//Here's the easy part. Create the Excel worksheet from the data set
ExcelLibrary.DataSetHelper.CreateWorkbook("MyExcelFile.xls", ds);
Enter fullscreen mode Exit fullscreen mode

Creating the Excel file is as easy as that. You can also manually create Excel files.

10. What is the best way to give a C# auto-property an initial value?

Answer:

In C# 5 and earlier, to give auto-implemented properties an initial value, you have to do it in a constructor.

Since C# 6.0, you can specify the initial value in-line. The syntax is:

public int X { get; set; } = x; // C# 6 or higher
Enter fullscreen mode Exit fullscreen mode

DefaultValueAttributeis intended to be used by the VS designer (or any other consumer) to specify a default value, not an initial value. (Even if in the designed object, the initial value is the default value).

At compile time DefaultValueAttribute will not impact the generated IL and it will not be read to initialize the property to that value.

Example of attributes that impact the IL are ThreadStaticAttribute, CallerMemberNameAttribute, …

Alternative Answer:

C# 6 :

With C# 6 you can initialize auto-properties directly.

C# 5 and below:

Though the intended use of the attribute is not to actually set the values of the properties, you can use reflection to always set them anyway.

public class DefaultValuesTest
{    
    public DefaultValuesTest()
    {               
        foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(this))
        {
            DefaultValueAttribute myAttribute = (DefaultValueAttribute)property.Attributes[typeof(DefaultValueAttribute)];

            if (myAttribute != null)
            {
                property.SetValue(this, myAttribute.Value);
            }
        }
    }

    public void DoTest()
    {
        var db = DefaultValueBool;
        var ds = DefaultValueString;
        var di = DefaultValueInt;
    }

    [System.ComponentModel.DefaultValue(true)]
    public bool DefaultValueBool { get; set; }

    [System.ComponentModel.DefaultValue("Good")]
    public string DefaultValueString { get; set; }

    [System.ComponentModel.DefaultValue(27)]
    public int DefaultValueInt { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

11. How to Sort a List by a property in the object?

Answer:

The easiest way is to use Linq:

List<Order> SortedList = objListOrder.OrderBy(o=>o.OrderDate).ToList();
Enter fullscreen mode Exit fullscreen mode

Alternative Answer:

If you need to sort the list in-place then you can use the Sort method, passing a Comparison<T> delegate:

objListOrder.Sort((x, y) => x.OrderDate.CompareTo(y.OrderDate));
Enter fullscreen mode Exit fullscreen mode

If you prefer to create a new, sorted sequence rather than sort in-place then you can use LINQ’s OrderBy method.

In Conclusion

These are the 11 most asked C# questions. If you have any suggestions or any confusion, please comment below. If you need any help, we will be glad to help you.

We, at Truemark, provide services like web and mobile app development, digital marketing, and website development. So, if you need any help and want to work with us, please feel free to contact us.

Hope this article helped you.

This article was first published on DevPost.

Top comments (0)