C#: You Don’t Know Jack

GEORGE HEERES

gheeres@gmail.com

http://blog.heeresonline.com

github.com/gheeres

AGENDA: Not really...

  • Strings
  • Little Known Features
  • H@ck1ng (decompiling)
  • Reflection for insight
  • Code Craftsmanship & Refactoring
  • Questions...

This is a loose outline.

PLEASE ask questions.

If we get side tracked, that is OK.

STRINGS: Oh my...

We’re going to start off looking at strings.

Lets face it, in line of business applications we spend a lot of time displaying, reading or modifying strings.

So it’s worth some the effort to get a little closer.

STRINGS: Old schoolz (the HARD way…)

  • Array of characters, null terminated
    • C
      • malloc()
      • memset()
      • sprintf(), strcpy(), etc.
  • Getting the length?
    • A smarter approach

H

E

L

L

O

\0

0x01

H

E

L

L

O

\0

0x01

5

H

E

L

L

O

0x01

Quick show of hands… how many C programmers do we have with us?

If you’ve been programming long enough, you’ll know that strings are “hard”.

In essence, strings are nothing more than a wrapper around an array of characters.

Now think about arrays? Not Lists or ArrayLists, but an actual array.

STRINGS: Old schoolz (the HARD way…) (continued)

  • Appending to the string
    • Space after string may be used by something else?

W

O

R

L

D

\0

2

H

E

L

L

O

\0

1

H

E

L

L

O

\0

1

X

Z

Buffer overflow!

\0

3

But how about appending to a string or changing the string?

How easy is it to resize that array?

We can’t just keep adding to the end of our existing memory.

Why not?

Because we don’t know what could be stored in memory after our currently allocated string.

This could be program code, variables, other strings, etc. This is the primary way that vulnerabilities occur. I overwrite your code instruction with my own code, etc.

Instead, we have to allocate an entirely new string of the necessary size.

A good C programmer will ensure that the end of the array is null terminated at this point.

STRINGS: Old schoolz (the HARD way…) (continued)

  • Appending to the string
    • Space after string may be used by something else?

W

O

R

L

D

\0

2

H

E

L

L

O

\0

1

H

E

L

L

O

\0

1

X

Z

H

E

L

L

O

\0

Buffer overflow!

3

Then copy the contents of the first string to our location.

STRINGS: Old schoolz (the hard way…) (continued)

  • Appending to the string
    • Space after string may be used by something else?

W

O

R

L

D

\0

2

H

E

L

L

O

\0

1

H

E

L

L

O

\0

1

X

Z

H

E

L

L

O

W

O

R

L

D

\0

Buffer overflow!

3

Copy the second string.

And lastly release or discard the memory references.

What interesting, is that typically the contents of the old string are not cleared.

The references to the memory are just discarded and marked as available.

STRINGS: What not to do?

string reason = "this is a long string " +
"that I've broken up into " +
"shorter lines so that it is " +
"easier for a developer to read " +
"because some architect said " +
"my lines of code must be under 80 " +
"characters...";
string response = "Horse pucky...";

What’s wrong with this code?

Can anyone tell me what is wrong with this code?

STRINGS: What not to do?

//000014: string reason = "this is a long string " +
//000015: "that I've broken up into " +
//000016: "shorter lines so that it is " +
//000017: "easier for a developer to read " +
//000018: "because some architect said " +
//000019: "my lines of code must be under 80 " +
//000020: "characters...";

IL_0001: ldstr "this is a long string that I've broken up into sho"
+
"rter lines so that it is easier for a developer to read because some ar"
+
"chitect said my lines of code must be under 80 characters..."
IL_0006: stloc.0

//000021: string response = "Horse pucky...";

IL_0007: ldstr "Horse pucky..."
IL_000c: stloc.1

Nothing!

Push a string object for the literal string.

Pop a value from stack into local variable 0.

1

this is...

STACK

0

this is a long string that I’ve broken up into...

The answer is nothing.

To see why, let’s look at the CIL code.

For some of you, this might be your first look at CIL code. We’re not going to get too in deep since I myself have only scratched the surface.

As part of the compilation, the C# compiler will actually recognize all of those constant strings and join them together.

When it comes to strings, the C# compiler has a lot of optimizations built into it.

CIL: A quick diversion

  • Stands for Common Intermediate Language
    • Formerly known as Microsoft Intermediate Language (MSIL)
    • Microsoft’s “answer” to Java Runtine Engine (JRE)
  • Runs on the Common Language Infrastructure (CLI)

Computer

*.vb

Compiler

*.cs

*.py

CLI

*.il

Machine Code

So we mentioned this CIL?

What is it?

In reality, the CIL is the language of .NET.

In fact, if you wanted, you COULD write in CIL natively…

Supporting a new language requires writing a code compiler that writes CIL code.

CIL: VB.NET to CIL vs C# to CIL

Dim reason As String = "this is a long string " &
"that I've broken up into " &
"shorter lines so that it is " &
"easier for a developer to read " &
"because some architect said " &
"my lines of code must be under 80 " &
"characters..."
Dim response As String = "Horse pucky..."

//000004: Dim reason As String = "this is a long string " &
//000005: "that I've broken up into " &
//000006: "shorter lines so that it is " &
//000007: "easier for a developer to read " &
//000008: "because some architect said " &
//000009: "my lines of code must be under 80 " &
//000010: "characters..."
IL_0001: ldstr "this is a long string that I've broken up into sho"
+
"rter lines so that it is easier for a developer to read because some ar"
+
"chitect said my lines of code must be under 80 characters..."
IL_0006:
stloc.0
//000011: Dim response As String = "Horse pucky..."
IL_0007: ldstr "Horse pucky..."
IL_000c:
stloc.1

//000014: string reason = "this is a long string " +
...

//000020: "characters...";
IL_0001: ldstr "this is a long string that I've broken up into sho"
+
"rter lines so that it is easier for a developer to read because some ar"
+
"chitect said my lines of code must be under 80 characters..."
IL_0006: stloc.0
//000021: string response = "Horse pucky...";
IL_0007: ldstr "Horse pucky..."
IL_000c: stloc.1

string reason = "this is a long string " +
"that I've broken up into " +
"shorter lines so that it is " +
"easier for a developer to read " +
"because some architect said " +
"my lines of code must be under 80 " +
"characters...";
string response = "Horse pucky...";

C#

VB

Comments excluded.

Still don’t believe me?

Here is the VB and C# versions of the code with the CIL output.

They are identical.

STRINGS: What not to do?

var fruits = new[] {"apple", "orange", "grape"};
string ul = "<ul>";
while(index < fruits.Length) {
ul +=
"<li>" + fruits[index] + "</li>";
index++;
}
ul +=
"</ul>";

What’s wrong with this code?

But what about the following code?

Is this OK?

Can anyone tell me what might be wrong here?

Now we have a problem.

We are creating a lot of temporary strings in memory and then discarding them as we keep building a bigger string.

STRINGS: System.Text.StringBuilder

var fruits = new[] {"apple", "orange", "grape"};
StringBuilder ul = new StringBuilder();
ul.Append(
"<ul>");
while(index < fruits.Length) {
ul.Append(
"<li>" + fruits[index] + "</li>");
index++;
}
ul.Append(
"</ul>");

  • Still need to be aware of string becoming too large.
    • Default capacity is 16 characters
    • Doubled whenever more characters are required

StringBuilder sb = new StringBuilder(); // Length = 0, Capacity = 16
sb.Append(
"1234567890123456"); // Length = 16, Capacity = 16
sb.Append(
"1"); // Length = 17, Capacity = 32
sb.Append(
"1234567890123456"); // Length = 33, Capacity = 64

65,536 chars => 131,072 chars

When concatenating strings, you should be using the StringBuilder class.

Here is how we would rewrite that first code.

A couple of caveats through.

You probably want to initial the initial size of the internal array which defaults to 16 characters.

As the length of the string increases, the capacity of the string is doubled.

At first, that might not be such a big deal, but going from 65536 -> 131072 or larger values could result in a lot of wasted memory.

STRINGS: IFormatProvider

var name = "George";
var language = "C#";
Console.WriteLine("Hello {0}. {0} has been writing {1} for more than decade...", name, language);
// Hello George. George has been writing C# for more than decade...

var money = 123.85;
String.Format("You owe me {0:C}...", money); // You owe $123.85...

var column = "012345678";
String.Format("| {0,-24} | {0,24} |", column);
// | 012345678 | 012345678 |

var padding = 11;
String.Format("ID: [{0,16:0-0000-0000}]", padding);
// ID: [ 0-0000-0011]

padding.ToString(
"###.000"); // 11.000

Console.WriteLine("Today: {0:ddd}, Time: {0:HH:mm} [{0}]", DateTime.Now);
// Today: Tue, Time: 22:16 [7/26/2016 10:16:08 PM]

  • C - printf(...) / sprintf(...)
    • %d = integer
    • %9.2f = 9 leading, 2 decimal
    • %s = string
    • %-32s = pad 32 characters
    • ...
  • Placeholder referenced by parameter index
  • IFormatProvider support
    • Console.WriteLine
    • String.Format
    • StringBuilder.AppendFormat
    • .ToString
  • Calls .ToString() on parameters by default
  • Formatting date/time

Let’s keep working with those strings.

A staple in any old C programmer was the printf(...) and sprintf(...) method calls to do formatting.

When formatting strings, you’d have %d or %s placeholders in the constant string you wanted output.

C# provides a similar mechanism but instead you use indexed placeholders in the string.

Automatically calls the .ToString() method for output.

One nice thing is you can reuse the same indexed value but format it separately.

This is all made possible by the IFormatProvider interface.

STRINGS: IFormatProvider Built-in Formatters

Lots of examples. Lots of flexibility and control.

  • Standard Numeric Format Strings
  • Custom Numeric Format Strings
  • Standard Date and Time Format Strings
  • Custom Date and Time Format Strings
  • Standard TimeSpan Format Strings
  • Custom TimeSpan Format Strings
  • Enumeration Format Strings

Format Specifier

Name

Example

“C” or “c”

Currency

(“C”, en-US) -> $123.46
("C", fr-FR) -> 123,46 €
(“C3”) -> $123.465

“D” or “d”

Decimal

("D") -> 1234

("D6") -> 001234

"M", "m"

Month/day

June 15

“T”

Long time

1:45:30 PM

...

...

...

There are dozens of prebuilt string formatters.

Use them!

STRINGS: IFormatProvider (continued)

public class Person {
public string LastName { get; set; }
}

Console.WriteLine("An object: {0}", new Person());
// An object: YouDontKnowJack.Program+Person

  • Objects
    • By default .ToString() will output the type

By default, when .ToString() is called on an object, the Type of the object is output.

We can solve that by overwriting the default .ToString() implementation.

STRINGS: IFormatProvider (continued)

public class Person {
public string LastName { get; set; }
public override string ToString()
{
return (LastName);
}
}

Console.WriteLine("An object: {0}", new Person() { LastName="Heeres" });
// An object: Heeres

  • To customize the default output, we simply override the .ToString() method.

Here we just return the value stored in the LastName property when .ToString() is called.

STRINGS: IFormatProvider Custom (continued)

public class TelephoneFormatter : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
return (formatType == typeof (ICustomFormatter) ? this : null);
}

public string Format(string format, object arg, IFormatProvider formatProvider)
{
if (format == null) format = "T";
string number = arg.ToString();

if (format == "T") {
if (number.Length < 10) {
throw new FormatException(String.Format("Formatter requires at least {0} digits", 10));
}
if (number.Length > 10) {
return(String.Format("({0}) {1}-{2} x{3}", number.Substring(0, 3),
number.Substring(3, 3), number.Substring(6, 4), number.Substring(10)));
}
return (String.Format("({0}) {1}-{2}",number.Substring(0, 3), number.Substring(3, 3),
number.Substring(6, 4)));
}
return (number);
}
}

  • We can even create our own custom formatters!
    • IFormatProvider
    • ICustomFormatter
  • But why bother?
    • Ensure telephone numbers all formatted the same
    • Account number formatting

String.Format(new TelephoneFormatter(), "Telephone: {0:T}", 1112223333);
// Telephone: (111) 222-3333

String.Format(new TelephoneFormatter(), "Telephone: {0:T}", 111222333344);
// Telephone: (111) 222-3333 x44

So wouldn’t it be nice if we could define our own custom formatters?

Perhaps to ensure that a telephone number is always formatted a particular way?

Or maybe a special format for an account number display (i.e. a dash at particular locations, etc.)

We can!

We just need to implement the IFormatProvider and ICustomFormatter interfaces.

Let’s go do that now...

STRINGS: IFormatProvider Custom Caveats (continued)

  • The BAD…
    • No way to globally register your custom formatter.
    • String.Format(IFormatProvider, format, args);

As good at the IFormatProvider sounds, unfortunately there is no way to globally register your custom formatter.

It must always be explicitly specified.

And only one ICustomFormatter can be specified at a time…

STRINGS: Interpolation (C# 6)

  • Simplifies the {0}..{N} indexing
    • Makes code more expressive and easier to read
    • Ensures that you don’t have index {2} in your string formatter when you only passed in 1 parameter.

var bee = new Bee() { Name = "Buzz" };
var flower = new Flower();
var honey = bee + flower;
var hive = $"See the bee named {bee.Name}...";

//000198: var hive = $"See the bee named {bee.Name}...";
IL_00af: ldstr "See the bee named {0}..."
IL_00b4:
ldloc.s bee
IL_00b6:
callvirt instance string YouDontKnowJack.Models.Bee::get_Name()
IL_00bb:
call string [mscorlib]System.String::Format(string,
object)
IL_00c0:
stloc.s hive

STRINGS: Debugging Helper (a quick detour / tidbit)

[DebuggerDisplay("[{Id}] {LastName}, {FirstName}")]
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}

var person = new Person() {
Id = 11100000,
LastName =
"Heeres",
FirstName =
"George"
};

  • By default, the debugger will display the .ToString() in the inspection

By default, the debugger will display the .ToString() implementation when inspecting the variable.

You can add a custom DebuggerDisplay attribute to your class to control how the watch / debugger displays the variable in the output window.

Little KNOWN Features

OPERATORS: Ternary

  • Ternary operator
    • Short-hand for if/else statement
    • condition ? true : false
  • Common way to check for null properties when traversing object
    • C#6: dice?.Value
  • NEVER nest them… makes the code VERY difficult to read

var value = (dice != null) ? dice.Value : 0;

// IS EQUIVALENT TO

if (dice != null) {
value = dice.Value;
}
else {
value = 0;
}

// BUT DON’T DO...

(dice != null) ? ((dice.Value > 6) ? 6 : dice.Value) : 0;

If you’ve ever seen the ?: syntax in code, you’ve probably wondered… what is that?

Most language support it, but until you know what it is called, it’s hard to learn more about it.

Not very easy to search on a ? in Google or programming.

The key is knowing that it’s called a ternary operator.

It is nothing more than a shorthand / shortcut for an if/else statement.

As tempting as it may be… DO NOT nest them inside of each other.

This is something I am personally guilty of.

I often associated less lines of code = good code… which isn’t true.

Readable code = good code.

It’s common to use the ternary operator when traversing the properties of an object where a property may be null.

C# 6 adds the ?. operator which further provides us a shortcut.

OPERATORS: Null Coalescing Operator

  • Shorthand for a null check
    • (left ?? right)
  • If left side is null, then use the right side
    • Useful to ensure that an object is non-null
  • Useful for lazy-loading of parameters
    • Why?
    • Save memory & overhead
      • Not created until accessed

string value = null;
value.ToLower();
// Can throw exception
var lower = (value ?? String.Empty).ToLower();

// Equivalent to

if (value == null) {
value =
String.Empty;
}

public class Cup
{
//private List<Dice> _dice = new List<Dice>();
private List<Dice> _dice;

public IEnumerable<Dice> Dice
{
get { return (_dice ?? (_dice = new List<Dice>())); }
}
}

The null-coalescing operator is a simple null check.

If the left side is null, then the right side is used.

Useful for ensuring you have a non-null value.

Use for lazy-loading of parameters.

Let’s assume we have millions of cups that MIGHT contain a dice.

The commented code will have a list preallocated for each dice regardless of if it is used.

With lazy loading, the list is not created until it is first accessed.

Saves memory.

OPERATORS: Implicit / Explicit

  • Implicit / Explicit conversion of object to other type
    • Implicit = no cast required
    • Explicit = cast required
      (typically “safer”, less unwanted side effects)
  • Note: Can also be accomplished with operator overloading (==, !=, etc.)

var person = new Person() {
Id = 10000000,
LastName =
"Heeres",
FirstName =
"George"
};
int id = 10000000;

if (person == id) {
}
//or may explicitly cast to an int
if ((int) person == id) {
}
//vs
if (person.Id == id) {
}

Have you ever found yourself wanting to write code similar to the right?

In C# this is possible using operators.

OPERATORS: Implicit / Explicit (continued)

public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }

public static implicit operator int(Person person)
{
if (person == null) return (0);
return (person.Id);
}

}

For explicit version, just change the implicit keyword to explicit

Here is how we’d write that code for implicit.

But you need to use implicit carefully because you can end up with some weird conversions and unintended comparisons.

OPERATORS: Overloads

  • Operators can be overloaded
    • +, -, !, ~, ++, --, true, false
    • +, -, *, /, %, &, |, ^, <<, >>
    • ==, !=, <, >, <=, >=

public class Bee
{
public string Name { get; set; }

public static Honey operator +(Bee bee, Flower flower)
{
if (flower == null) return (null);
return (new Honey());
}
}

public class Flower
{
public string Type { get; set; }
}

public class Honey
{
public string Quality { get; set; }
}

var bee = new Bee();
var flower = new Flower();
var honey = bee + flower;

Operators (+, -, etc.) can all be overloaded.

ENUMERABLE: yield return what?

  • Only runs code as values are enumerated
  • WARNING
    • SQL database connections may already be closed by the time you enumerate
    • Technically violates the MVC pattern (data is “retrieved” in the view when enumerated)
      • Use .ToArray() or other method that will force all items to be “read”

public IEnumerable<B> Convert(IEnumerable<A> a)
{
foreach(var item in a) {
yield return item.ToB();
}
}

OK. Some of you may have seen the special yield keyword and be wondering what that does?

Yield is an native way to do lazy loading of items.

Instead of converting all of the items at once, items are only converted as they are used.

While it’s a nice optimization, keep in mind that it can cause some problems.

For example, if you’re reading from a database, by the time you attempt to iterate over the collection, the underlying DB connection may be closed.

BIT MATH: What is | or &?

  • Enumerations can have the [Flags] attribute added which means multiple values (bits) can be set at the same time.

[Flags]
enum Direction
{
None = 0,
Left = 1,
// 0x1 << 0
Right = 2,
// 0x1 << 1
Up = 4,
// 0x1 << 2
Down = 8
// 0x1 << 3
}

0

1

1

0

8

4

2

1

6

=

Left

Right

Up

Down

6 = Right, Up

Probably the most confusing thing for people is when they see the binary OR or AND operators.

That is what the | and & symbols mean.

To understand how they work, we need to go back to our computer science days.

If you recall a computer is binary. It’s either 1 or 0.

Everything is a power of two.

So each bit position (32 bits total in a integer)

2^0 = 1

2^1 = 2

2^2 = 4

2^3 = 8

So the binary representation of the number 6 would be 0110.

With the flags attribute, instead of 32 bits representing one value, we allow each bit to represent a value.

That allows for an enumeration to have more than one value at a time.

BIT MATH: Enum Helpers (continued)

var direction = Direction.Down | Direction.Up;

if (((direction & Direction.Up) == Direction.Up)) {
}

// or more simply
if (direction.HasFlag(Direction.Up)) {
}

Both Down & Up
(i.e. vertical)

[Flags]
enum Direction
{
None = 0,
Left = 1,
// 0x1 < 0
Right = 2,
// 0x1 < 1
Up = 4,
// 0x1 < 2
Down = 8,
// 0x1 < 3
Vertical = Up | Down,
Horizontal = Left | Right,
Omni = Vertical | Horizontal
}

So typically when dealing with an enum that has the [Flags] attribute, you’ll see it being interacted with like the following.

Of course, if we’re going to be using some concepts or groups, we can created dedicated enums to make our code more readable and easier to understand.

CONSTRUCTORS: DRY > “Daisy Chain”

  • DRY
    • Don’t
    • Repeat
    • Yourself
  • Two solutions
    • Common initializer
    • Daisy Chain constructor

public class Dice
{
public int Value { get; set; }

public Dice(int value)
{
Value = value;
}

protected Dice(Dice dice)
{
Value = dice.value;
}
}

public class Dice
{
public int Value { get; set; }

public Dice(int value)
{
Initialize(dice.Value);
}

protected Dice(Dice dice)
{
if (dice != null) {
Initialize(dice.Value);
}
}

protected void Initialize(int value)
{
Value = value;
}

}

public class Dice
{
public int Value { get; set; }

public Dice(int value)
{
Value = value;
}

protected Dice(Dice dice):this((dice!=null) ? dice.Value : 0)
{
}
}

Another common mistake I see is people creating multiple constructors with the same initialization code.

This simply violates the DRY principal.

Two solutions.

Create a method that contains the initialization code.

Or daisy chain the constructors “up” or “down”...

EXTENSIONS: I U!!!

  • Introduced with LINQ
  • “Extend” functionality of classes
  • Syntactic sugar

More later… TIME permitting!

In my opinion, one of the greatest things that happened to the C# language was the extension methods that were introduced with LINQ.

They allow for a class to have functionality added without having access to or modifying the original code.

As magical as they seem, they are really just Syntactic sugar made possible by the magic of the compiler.

H@ck1ng: decompiling for Insight

H@ck1ng: Decompiling Code

  • JetBrains dotPeek
    https://www.jetbrains.com/decompiler/
  • ILSpy
    http://ilspy.net/
  • Telerik JustDecompiler
    http://www.telerik.com/products/decompiler.aspx
  • .NET Decompiler (formerly Redgate Reflector)
    http://www.red-gate.com/products/dotnet-development/reflector/

Next, we’re going to look at decompiling code.

Why would we want to do that?

To get an understanding of how a library works or what might be happening internally.

Or possibly if the original source code was lost.

There are a number of different products available.

I’m partial and prefer JetBrains dotPeek.

Let’s see what this looks like.

Lets look at the HttpServerUtility.EncodeHtml utility.

System.Web -> HttpServerUtility

HtmlEncode -> HttpUtility.HtmlEncode

HttpEncoder -> WebUtility.HtmlEncode

So that was the 4.0 library…

What about an older version of the library?

Open C:\Windows\Microsoft.NET\Framework64\v2.0.50727\System.Web.dll

We can see that the newer implementation is more extensible and pluggable than the old.

H@ck1ng: OH *snap*...

  • So easy...
  • But how can I stop?
    • Don’t store sensitive data?
    • Move algorithms to web based / remote services
    • .Net obfuscator
      https://en.wikipedia.org/wiki/List_of_obfuscators_for_.NET

Anytime you have the bits, it’s “GAME OVER”... eventually.

With enough time and effort anything can be reverse engineered or cracked…
So don’t ship code… use REST / web services...

So now some of you might be thinking… Oh crap…

We have proprietary information in there?

You mean to tell me that anyone can view our custom algorithms…

More or less… YES.

REFLECTION: It’s just metadata

REFLECTION: What is private?

public class CreditCard
{
private int Id;
public string Name { get; set; }

public CreditCard(int id, string name = null) {
Id = id;
Name = name;
}

private float ChargeIt(float amount) {
return (-1 * amount);
}


public string ToJson() {
return(String.Format(
"{{ id: {0:XXXX XXXX XXXX 0000}, name: \"{1}\" }}",
Id % 10000, Name));
}
}

  • Access modifiers
    • public
    • protected
    • internal
    • private
  • private keyword
    • Can’t access from outside of the class.
    • Can’t access from subclass.

So lets take a quick look at our access modifiers.

Public - can be access from everywhere

Protected - can only be access from subclasses

Internal - can be access from inside the assembly / namespace

Private - can only be access from within the class

Do you agree that private variables are hidden?

REFLECTION: What is private? (continued)

var cc = new CreditCard(11112222, "George Heeres");
Type type = typeof(CreditCard); // cc.GetType();
Console.WriteLine("CC: {0}", cc.ToJson());
// CC: { id: XXXX XXXX XXXX 2222, name: "George Heeres" }

public class CreditCard {
private int Id;
public string Name { get; set; }

public CreditCard() {

}

private float ChargeIt(float amount) {

}



}

FieldInfo field = type.GetField("Id",
BindingFlags.Instance | BindingFlags.NonPublic);
Console.WriteLine("Field: {0}", field.GetValue(cc));
// Property: George Heeres

PropertyInfo property = type.GetProperty("Name");
Console.WriteLine("Property: {0}", property.GetValue(cc));
// Field: 11112222

MethodInfo method = type.GetMethod("ChargeIt",
BindingFlags.Instance | BindingFlags.NonPublic);
Console.WriteLine("Method: {0}", method.Invoke(cc, new object[] { 1000 }));
// -1000

So, let’s go ahead and create an instance of our class. Then we’ll grab the type of the object. This can be done statically or dynamically.

For a property (anything with getters and setters), we use the GetProperty() method of the type.

In this case, because it is a public field, we don’t it’s pretty simple.

Once we get the property information, we just call the GetValue method passing in the instance that we are workign with.

So if we want to access a field, which is an constant or variable not declared as a property, we use the GetField call on the type.

In this case, because we are going after private values, we need to explicitly tell the reflection methods to inspect those.

By default, if the BindingFlags are not specified, then Instance | Public are assumed.

Once we have our field, it’s the same as getting a property.

There are also SetValue methods available.

Lastly, to get a function or method, we use the GetMethod().

We specify the name and then our binding flags. Because this is again non public, we need to be explicit.

Note: If you have overloaded methods, then you will need to specify an array of types that match the signature of the method you want.

Once we have our method, we can Invoke it. When we invoke it, we pass in the object we are working with, and then an array of our parameters.

REFLECTION: Static

public class Apple
{
protected Apple()
{
}

public static Apple Create()
{
return (new Apple());
}
}

Type type = typeof (Apple);
MethodInfo method = type.GetMethod("Create",
BindingFlags.Static | BindingFlags.Public);

var apple = (Apple) method.Invoke(null, null);
Console.WriteLine("Apple: {0}", apple);
// Apple: YouDontKnowJack.Models.Apple

So let’s assume we have the class on the right.

Here we have made the constructor private because we don’t want anyone to be able to create new objects.

We want to force them to go through our “factory”.

So like before, the first step is to grab the type.

Then we grab the method information, but this type instead of specifying instance, we specified static.

When we invoke the method, the first parameter asks for the instance that we’re using.

Because this is static, there is NO instance so we can just specify null.

REFLECTION: Generics Too?

public class Lookup<T>
{
public T Id { get; set; }
public string Name { get; set; }

public Lookup()
{
}

public Lookup(T id, string name): this()
{
Id = id;
Name = name;
}

public string ToJson()
{
return (String.Format(
"{{ id: {0}, name: \"{1}\" }}", Id, Name));
}
}

Type type = typeof (Lookup<>);
Type genericType = type.MakeGenericType(new[] {
typeof (int)
});
Lookup<int> tag = (Lookup<int>)
Activator.CreateInstance(genericType);
Console.WriteLine("Tag: {0}", tag.ToJson());
// Tag: { id: 0, name: "" }

// or

var constructor = genericType.GetConstructor(new[] {
typeof (int),
typeof (string)
});
Lookup<int> tag2 = (Lookup<int>)
constructor.Invoke(
new object[] {1, "Retired"});
Console.WriteLine("Tag: {0}", tag2.ToJson());
// Tag: { id: 1, name: "Retired" }

We can also create generics, although it takes a little more effort.

First thing it to get the type definition.

Then to create the actual generate type from that type definition.

Once done, we can then use the Activator.CreateInstance method.

Optionally, you can retrieve the constructor and then call it.

REFLECTION: A Practical Example

public enum Curriculum
{
CIS = 120,
EDUC = 130,
MATH = 100,
BIO = 110
}

  • Add additional data to any element
    • Enum
    • Field
    • Class
    • Property
    • Etc.
  • Keep similar data close together to avoid potential mismatch

public enum Curriculum
{
[
DisplayName("Computer Information Systems")]
CIS = 120,
[
DisplayName("Education")]
EDUC = 130,
[
DisplayName("Mathematics")]
MATH = 100,
[
DisplayName("Biology")]
BIO = 110
}

REFLECTION: A Practical Example (continued)

[AttributeUsage(AttributeTargets.All)]
public class DisplayNameAttribute: Attribute
{
public string DisplayName { get; set; }

public DisplayNameAttribute(string displayName)
{
DisplayName = displayName;
}
}

REFLECTION: A Practical Example (continued)

public static class CurriculumExtensions
{
public static string GetDisplayName(this Curriculum curriculum)
{
Type type = curriculum.GetType();
FieldInfo field = type.GetField(curriculum.ToString());
var attributes =
field?.GetCustomAttributes(
typeof(DisplayNameAttribute),
true);
if (attributes?.Length > 0) {
var attribute = attributes.OfType<DisplayNameAttribute>()
.FirstOrDefault();
if (attribute != null) {
return (attribute.DisplayName);
}
}
return (String.Empty);
}
}

Curriculum curriculum = Curriculum.CIS;
Console.WriteLine("[{0}] {1}={2}",
(
int) curriculum, curriculum,
curriculum.GetDisplayName());

// [120] CIS=Computer Information Systems

Craftsmanship: REFACTORING

Boy Scout Rule: Always leave the campground cleaner than you found it.

OK. Let’s take a brief interlude to refactor that code.

When we consider that the majority of “expense” for code is in maintenance, we need to make sure that our code is easy to maintain.

The boy scouts have a rule: Alway leave the campground cleaner than you found it.

As a software craftsman, this should be your rule as well.

Always leave the code in a better state than when you first entered it.

If everyone followed that, then the code would resist rot a lot longer.

REFACTORING: “Magic” Numbers

public class TelephoneFormatter : …
{

public const int MinimumLength = 10;

public string Format(…)

{
if (number.Length < 10) {

}
if (number.Length >= 10) {

}
}
}

  • Any static constants in code should be made as constants for maintenance.

public class TelephoneFormatter :
{

public const int MinimumLength = 10;

public string Format(…)

{
if (number.Length < MinimumLength) {

}
if (number.Length >= MinimumLength) {

}

}

}

So first thing is to get rid of the “magic” numbers and constants in our code and to give them a name.

OK. So we change the first one, but does anyone see that we missed a second one?

This is a bug waiting to happen.

So let’s create a constant to represent that and use it.

Now if we need to change that length, we only need to change one reference in our code.

REFACTORING: Be Expressive & Declare Intent

public class TelephoneFormatter : …
{

public string Format(…)

{
if (number.Length < MinimumLength) {

}

}
}

  • Write code that reads like english

public class TelephoneFormatter :
{

private bool IsPhoneNumber(string value)

{

if (String.IsNullOrEmpty(value)) {

return (false);

}

return (value.Length >= MinimumLength);

}

public string Format(…)

{
if (! IsPhoneNumber(number)) {

}
}

}

OK. So when we are checking the length, what are we really doing?

We are doing a rudimentary check to see if the number being passed in looks like a telephone number.

How about instead we write a method called IsPhoneNumber()

Now someone that comes back in can quickly read that line and know what we are checking for.

REFACTORING: Be Expressive & Declare Intent (continued)

public class TelephoneFormatter : …
{

public string Format(…)

{
// Check for country code prefix
if (! ((value.Length == MinimumLength) ||
(value.StartsWith("1") &&
(value.Length == (MinimumLength+1))))) {

}

}
}

  • New requirement - handling of possible country codes.

public class TelephoneFormatter :
{

private bool HasExtension(string value)
{
if (String.IsNullOrEmpty(value)) {

return (false);

}
return (…);
}

public string Format(…)

{
if (HasExtension(number)) {

}
}

}

GOOD code is self documenting!

But what happens if have a new requirement that says that states that a number may have the international code 1 appended.

In this case, it’s easier to just identify what a normal phone number might look like and then negate the results.

With this example, it’s now a lot more difficult to understand what we’re looking for?

We have to study the code… and even then, we don’t really know what the original business rules might be.

After we refactor, the code is much more expressive and easier to read.

I can glance at that and know what it's doing.

And guess what, no comments are necessary.

The code is SELF documenting.

Some of you may probably recognize that we should probably create a new method to detect a country code.

i.e. HasCountryCode()

REFACTORING: String Comparisons

var person1 = "GeOrGe";
var person2 = "GEROLD";

if (person1 == person2) {
}


  • Case insensitive comparison
    • ToLower() / ToUpper()
      • Inefficient…

if (person1.ToLower() == person2.ToLower()) {
}

G

e

O

r

G

e

G

E

R

O

L

D

g

e

o

r

g

e

g

e

r

o

l

d

G

e

O

r

G

e

G

E

R

O

L

D

if (String.Equals(person1, person2,
StringComparison.OrdinalIgnoreCase)) {
}

G

e

O

r

G

e

G

E

R

O

L

D

1

2

3

E

e

e

e

Probably one of the biggest mistakes and inefficiencies I see is with string comparisons, in particular when it should be case insensitive.

Obviously the first option we know would be case sensitive.

So if someone wants it to be case insensitive, we typically see the approach to either convert it all to uppercase or all to lowercase and then do the comparison.

Obviously you can see there is a lot of wasted effort here.

We converted 6 characters that didn’t need to be compared.

That may not seem like a lot, but what about larger blocks of text?

The preferred method is to use the String.Equals static method which takes a StringComparison strategy.

The framework is optimized to look at the elements of our string (which is basically an array of characters) one at a time.

STRINGS: StringComparison

Name

Description

CurrentCulture

Compare strings using culture-sensitive sort rules and the current culture.

CurrentCultureIgnoreCase

Compare strings using culture-sensitive sort rules, the current culture, and ignoring the case of the strings being compared.

InvariantCulture

Compare strings using culture-sensitive sort rules and the invariant culture.

InvariantCultureIgnoreCase

Compare strings using culture-sensitive sort rules, the invariant culture, and ignoring the case of the strings being compared.

Ordinal

Compare strings using ordinal (binary) sort rules.

OrdinalIgnoreCase

Compare strings using ordinal (binary) sort rules and ignoring the case of the strings being compared.

For the String.Equals method, there are 6 recognized types.

Typically we only use the bottom two which are the comparison operations that we expect.

REFACTORING: Intellisense

public class TelephoneFormatter : …
{

/// <summary>
/// Checks to see if the specified phone number
/// has extension information embedded.
/// </summary>
/// <param name="value">The phone number to inspect.</param>
/// <returns>True if the phone number has extension,
/// false if otherwise.</returns>
private bool HasExtension(string value)
{
return(…);
}
}

  • XmlDoc
    • Don’t be lazy… leave the future you clues!
  • Autogenerated API documentation (just like MSDN) via SandCastle or other tools

Quick show of hands…

Who likes intellisense?

How would you like all of your code or libraries to have intellisense?

You can!

Just write XmlDoc.

You just have to quit being lazy.

It’s not someone else’s problem to generate documentation.

Make it a part of your code conventions.

Even constants and enums can have XmlDoc added.

As a bonus, that same XmlDoc can be run through SandCastle or another tool to automatically generate your API documentation.
Where do you think all of that nice MSDN documentation comes from?

REFACTORING: Your Turn...

public bool IsReady(string value)
{
bool result = false;
if (value.ToLower() == "ready") {
return (true);
}
else {
return (false);
}
}


if
(IsReady("not")) {
}

  • Common example
    • What is done right?
    • Can you spot the problems?

public bool IsReady(string value)
{
return(
String.Equals(value, "ready",
StringComparison.OrdinalIgnoreCasevalue));
}

So this is a typical example that I see of code.

What is done right?

Nicely named. Reads like English. Perhaps could be even more descriptive?

Based on what we’ve just gone over, can you find any problems with this code.

Let’s refactor this together.

No function comments.

No null checking of value.

Unoptimized string checking.

Can be reduced to single statement.

List<T> PROPERTIES: Be Wary...

  • Be VERY careful returning POCO objects which properties that contain IList<T> or List<T>
    • POCO
      • Plain Ole’ CLR Object
  • Why?
    • Confusing to consumers of object.
      • Why didn’t my add, actually add or persist the changes?

public class Cup
{
private List<Dice> _dice;

public IList<Dice> Dice
{
get {
return (_dice ?? (_dice = new List<Dice>()));
}
}
}

Cup cup = new Cup();
cup.Dice.
Add(new Dice(1));

Implies functionality…

When dealing with POCO (plain ole’ CLR objects), you should almost NEVER return an IList<T> or List<T> type.

Why? It implies that the consumer can just “add” or remove items…

They they are confused with how you might persist.

When creating your classes, it’s all about trying to write your code defensively so that people don’t utilize you code wrong.

Almost always you should be returning an IEnumerable<T> instead of a List<T>.

EXTENSIONS: DTO

  • N-Tiered Development
    • Data Transfer Object (DTO)
    • Common problem

WebAPI

Business Layer

Data Access Layer

Model
A

A

A

A

HTML

A

Our database schema has “leaked” into our presentation layer!

So, today the generate consensus is that N-tiered development is preferred.

Here we have a depiction of a typical N-tiered architecture.

Can anyone tell me what is wrong with this?

Correct.

The underlying database has “leaked” into our presentation layer and is now tightly coupled.

Any change to our underlying data model requires a change to EVERY layer in our tier.

Lets look at the right way...

EXTENSIONS: DTO (continued)

  • Model per tier
  • Only dependent on layer immediately below
  • Should not know anything about consumer (layer above)

WebAPI

Business Layer

Data Access Layer

Model
A

HTML

A

B

C

B

D

C

Correct.

To avoid a “ripple” effect caused by changes, each layer should have it’s own model and only dependent on the model immediately below it.

Now, if the database table changes. I only need to update two layers.

The data access layer and then the transformation of the A model to the B model in the business layer

EXTENSIONS: Example

public class A // Data access Layer
{
public int RowId { get; set; }
public int EmployeeId { get; set; }
public string Name { get; set; }
public int Status { get; set; }
}

public class B // Business rules Layer
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsRegistered { get; set; }
}

public class C // WebAPI / service layer
{
public int Id { get; set; }
public string Name { get; set; }
}

A a = new A() {
RowId = 1,
EmployeeId = 10000000,
Name =
"George",
Status = 10
};
B b = a.ToB();

public class A {
..
public B ToB() {
return (new B() {
Id = EmployeeId, Name = Name,
IsRegistered = ((Status % 2) == 1)
});
}
}

OK. So let’s create some sample models to illustrate this.

We have our initial model A which mimics our database structure.

Then for our business layer, we drop the fields we aren’t interested in.

And we add some business rules that define what “IsRegistered” means.

And lastly, our export drops the IsRegistered property because it was only used internally within the business layer for additional processing.

So, what we’d like to do, is write the code at the right.

At any point in time, if we want to convert an A object to a B object, we can just call a ToB() method.

Now the first thought would be to create a method on the A class that does this conversion.

The logic is pretty straight forward. We just do a right to left mapping. Some of you may recognize tools like StructureMap which can help you do this.

But sometime those tools are overkill and more overhead than necessary.

However this causes us a problem. The lower layer is NOW dependent on the upper layer.

If the classes are all in the same project, this isn’t a problem, but they most likely would live in other libraries.

So how do we do this...

EXTENSIONS: Example (continued)

/// <summary>
/// Extension methods for the <see cref="A"/> class.
/// </summary>
public static class AExtensions
{
/// <summary>
/// Converts an instance of <see cref="A"/> into an instance of <see cref="B"/>.
/// </summary>
/// <param name="a">The object to convert.</param>
/// <returns>The converted instance.</returns>
public static B ToB(this A a)
{
if (a == null) return (null);
return (new B() {
Id = a.EmployeeId,
Name = a.Name,
IsRegistered = ((a.Status % 2) == 1)
});
}
}

B b = a.ToB();
B b2 = AExtensions.ToB(a);

So to do this, we create a static class with a static method that uses the special “this” keyword.

We can call this two different ways.

One using the more natural method.

Or using the actual static declaration.

EXTENSIONS: Syntactic Sugar - CIL Inspection

//000135: B b = a.ToB();
IL_00bd: ldloc.s a
IL_00bf:
call class YouDontKnowJack.Models.B YouDontKnowJack.Models.Extensions.AExtensions::ToB(class
YouDontKnowJack.Models.A)
IL_00c4:
stloc.s b

//000136: B b2 = AExtensions.ToB(a);
IL_00c6: ldloc.s a
IL_00c8:
call class YouDontKnowJack.Models.B YouDontKnowJack.Models.Extensions.AExtensions::ToB(class
YouDontKnowJack.Models.A)
IL_00cd:
stloc.s b2

If we inspect the CIL output, we see that the same exact code is generated.

Extension methods are nothing more than syntactic sugar.

At compile time, the static method calls are generated.

EXTENSIONS: More… Support IEnumerable

public static class AExtensions
{
public static B ToB(this A a)
{

}

/// <summary>
/// Converts an collection of <see cref="A"/> into a collection of <see cref="B"/>.
/// </summary>
/// <param name="a">The collection of items to convert.</param>
/// <returns>The converted instance.</returns>
public static IEnumerable<B> ToB(this IEnumerable<A> a)
{
foreach(var item in a) {
yield return item.ToB();
}
//return(a.Select(item => item.ToB()));
}
}

var incoming = new A[] {new A(), new A()};
var outgoing = incoming.ToB();

But, since we’re almost there, why not also make it easy to convert a collection of A’s to B’s.

To do that, we just iterate over the items and do a yield return with a conversion for each item.

Or optionally, we can just write that same statement as a single line of LINQ.

To the right is the example of how we might use that.

QUESTIONS: More?

GEORGE HEERES
gheeres@gmail.com
http://blog.heeresonline.com
github.com/gheeres