Thursday, December 14, 2017

typeof vs nameof


Skip to end of metadata

Go to start of metadata
Recently had a discussion with a fellow dev regarding the difference between typeof(T).Name and nameof(T).
It is a lot more performant to use nameof keyword if you are just trying to get the string name of type as opposed to typeof(T).Name.

Let's look at an following example.

Given a simple C# console app as follows:
a console app
1
2
3
4
5
6
7
8
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(typeof(Program).Name);
        Console.WriteLine(nameof(Program));
    }
}

The compiler generates the following IL:
generated IL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       34 (0x22)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldtoken    typeof_nameof.Program
  IL_0006:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
  IL_000b:  callvirt   instance string [mscorlib]System.Reflection.MemberInfo::get_Name()
  IL_0010:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0015:  nop
  IL_0016:  ldstr      "Program"
  IL_001b:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0020:  nop
  IL_0021:  ret
// end of method Program::Main

Notice nameof is turned into a string "Program"? while typeof(Program).Name generated code to execute get_Name(). typeof is definitely a runtime evaluation.
Naturally string literal requires almost zero calculation at runtime therefore it is a more performant one.  In conclusion, we should favor it over typeof(T).Name

Saturday, October 21, 2017

GIT Config Settings and their Precedence

logo2x

It is helpful to setup GIT default user name and email so you don't have to type it every time when you push commits to remote.  At the same time, you may have different remote accounts such as github, bitbucket etc. with different user names and emails.  So how do you manage that?  Fortunately, GIT designers have already thought about this.  GIT config command comes with three different options:
$ git config --system user.name "terry yakky" $ git config --system user.email terry@example.com
$ git config --global user.name "barry yakky" $ git config --global user.email barry@example.com
$ git config --local user.name "larry yakky" $ git config --local user.email larry@example.com

--system option

The specified user name and email value apply for every user of the computer on the system and all of the repositories.  The config file is stored at /etc/gitconfig

--global option

The specified user name and email values apply to the current logged in user and all of the repositories under this login.  The config file is stored at ~/.gitconfig (or ~/.config/git/config)

--local option

The specified user name and email values apply to the current repository directory.  The config file is stored at .git/config in the GIT directory.

And the precedence is local trumps global, global trumps system.  If a setting is not found in local, GIT looks for it in global, if not in global, in system.

And this precedence and fallback rule apply to other config settings as well.

Sunday, May 4, 2014

An architectural decision and a simple custom sorting

Context:

Recently, I worked on a requirement that required a list of job schedules to be sorted according to priorities imposed on the value of a property of the job schedule, on a ASP.NET MVC view of a web app.  I can put the logic that sorts the data anywhere in the stack to meet this particular requirement.  I could put the sorting logic in the SQL query, or in the repository method after getting the data, or I can sort the data at the controller level before feeding to it to the view that renders it.   The SQL query and the repository method are used by other code that doesn’t need the data sorted so I’d be adding undue burden to other code when the data doesn’t need to be sorted.  I decided to sort the data at the controller level.  This is a trieval design decision but I think this thought process is important to ensure the scalability of your application architecture.

The Requirement:

Given the schedule priority with the following values:
“A” : AM
“P” : PM
“O” : Any time
“F”  : First

the schedule list should be sorted in the following order:
  1. “F”  : First
  2. “A” : AM
  3. “O” : Any time
  4. “P” : PM

As you can see from the data I cannot sort the list using the values’ alphabetical order.  That means I need to create a custom comparer to be used to the value in this manner.

The Code:

Here is the job schedule class:
public class JobSchedule
{
public string Customer { get; set; }
public string SchedulePriority { get; set; }
public override string ToString()
{
    return string.Format("{0} :: {1}", Customer, SchedulePriority);
}
}
The priority class:
public class SchedulePriority
{
public SchedulePriority(string code, string description)
{
    Code = code;
    Description = description;
}
public string Code { get; private set; }
public string Description { get; private set; }
public override string ToString()
{
    return string.Format("{0} :: {1}", Code, Description);
}
}
Below is a sample list data:
var list = new List<JobSchedule>{
new JobSchedule{
    Customer = "jon",
       SchedulePriority = new SchedulePriority("P","PM")
},
new JobSchedule{
    Customer = "jane",
       SchedulePriority = new SchedulePriority("O","Any")
},
new JobSchedule{
    Customer = "bob",
       SchedulePriority = new SchedulePriority("A","AM")
},
new JobSchedule{
    Customer = "bonnie",
       SchedulePriority = new SchedulePriority("F","First")
},
};
The requirement is to sort is this order:
“F”, “A”, “O”, “P”
If I were to sort it alphabetically as the following:
    Console.WriteLine("Sort by Alphabetical Order and the result does NOT match the requirement");
    foreach (var js in list.OrderBy(m => m.SchedulePriority.Code))
    {
        Console.WriteLine(js.ToString());
    }
This is the result I get:
Sort by Alphabetical Order and the result does not meet the requirement
bob :: A :: AM
bonnie :: F :: First
jane :: O :: Any
jon :: P :: PM
So we create a custom comparer by implementing the ICompare interface:
public class SchedulePriorityOrderComparer : IComparer<SchedulePriority>
{
readonly Dictionary<string, int> _priorities = new Dictionary<string, int>() {
    {"F", 1},
    {"A", 2},
    {"O", 3},
    {"P", 4}
};
public int Compare(SchedulePriority x, SchedulePriority y)
{
    if (string.IsNullOrWhiteSpace(x.Code) || string.IsNullOrWhiteSpace(y.Code)) return 0;
    return _priorities[x.Code] - _priorities[y.Code];
}
}
Now I can sort it this as follows:
Console.WriteLine("Sort by Alphabetical Order and the result MATCH the requirement");
foreach (var js in list.OrderBy(m => m.SchedulePriority, new SchedulePriorityOrderComparer()))
{
        Console.WriteLine(js.ToString());
}
And the result now looks like this:
Sort by custom order and the result MATCH the requirement
bonnie :: F :: First
bob :: A :: AM
jane :: O :: Any
jon :: P :: PM

Full code list:

A sample cosole app has been created as a gist here on GitHub  to demo the approach.

About Cullen

My photo
Christian, Father, Software Developer/Architect who enjoys technology and using it to make people's lives easier!

Followers