This article will discuss how to use extension method to encapsulate if/else,swith/case and while. Through these extensions the written code will seldom use curly brackets. What about this extension, maybe you have better advice .Please let me know.
Proclamation: This article just wanted to express a thought. And the code provided only an example, which can be tested successfully ,but imperfect.
Firstly, let us see if/else, and switch/case, both of which in the code are used as branched structure. Here, we encapsulate them into an “If “extension:
public static T If<T>(this T t, Predicate<T> predicate, Action<T> action) where T: class
{
if(t == null) throw new ArgumentNullException();
if (predicate(t)) action(t);
return t;
}
See the following code to call, which will generate a people instance:
public static void Test1()
{
//General Code
People people1 = new People { Name = “ldp615″, IsHungry = true, IsThirsty = true, IsTired = true };
if (people1.IsHungry) people1.Eat();
if (people1.IsThirsty) people1.Drink();
if (people1.IsTired) people1.Rest();
people1.Work();
People people2 = new People { Name = “ldp615″, IsHungry = true, IsThirsty = true, IsTired = true }
.If(p => p.IsHungry, p => p.Eat())
.If(p => p.IsThirsty, p => p.Drink())
.If(p => p.IsTired, p => p.Rest());
people2.Work();
}
We used Lambda expression in the If extension code .If the preceding “p=>p” can be moved ,it will be better.
The Class People is as follows:
public static void Test1()
{
People people1 = new People { Name = “ldp615″, IsHungry = true, IsThirsty = true, IsTired = true };
if (people1.IsHungry) people1.Eat();
if (people1.IsThirsty) people1.Drink();
if (people1.IsTired) people1.Rest();
people1.Work();
// /Use extension method
People people2 = new People { Name = “ldp615″, IsHungry = true, IsThirsty = true, IsTired = true }
.If(p => p.IsHungry, p => p.Eat())
.If(p => p.IsThirsty, p => p.Drink())
.If(p => p.IsTired, p => p.Rest());
people2.Work();
}
For the reference type, we can use Action, and also use chain programming mode to string several If. However, for a value type, we can use Func to return a new value every time.
public static T If<T>(this T t, Predicate<T> predicate, Func<T, T> func) where T : struct
{
return predicate(t) ? func(t) : t;
}
It is necessary to modify the code called.
public static void Test2()
{
// /Use extension method
int int0 = -121;
int int1 = int0.If(i => i < 0, i => -i)
.If(i => i > 100, i => i - 100)
.If(i => i % 2 == 1, i => i - 1);
// General code
int int3 = -121;
if (int3 < 0) int3 = -int3;
if (int3 > 100) int3 -= 100;
if (int3 % 2 == 1) int3–;
}
The extension of the reference type and value type have been completed .Now ,we can use string to test it :
public static void Test3()
{
//Transform the mailbox into a home page .
string email = “ldp615@163.com”;
string page = email.If(s => s.Contains(“@”), s => s.Substring(0, s.IndexOf(“@”)))
.If(s =>! s.StartsWith(“www.”), s => s = “www.” + s)
.If(s =>! s.EndsWith(“.com”), s => s += “.com”);
}
But the compilation can not be passed, and prompt an error.
This error looks strange .We have written two extensions, one is for value type, other is for reference type. But the Class string can not be passed here.
However, we can write specifically an extension for string to resolve this problem. The code is as follows:
public static string If(this string s, Predicate<string> predicate, Func<string, string> func)
{
return predicate(s) ? func(s) : s;
}
From the above code, we find that there is a priority in the extension method: on the same class, we can do the extension for several times. When there is the same extension, equivalent parameters (the same number and sequence), and the priority of the non generic extension is higher than generic extension.
Let us see a swith code, which is very long-winded. In order to elicit extension, we had to write the following code:
public static void Test4()
{
string englishName = “apple”;
string Name = string.Empty;
switch (englishName)
{
case “apple”:
Name = “Apple”;
return;
case “orange”:
Name = “Orange”;
return;
case “banana”:
Name = “Banana”;
return;
case “pear”:
Name = “Pear”;
break;
default:
Name = “unknown”;
break;
}
Console.WriteLine(chineseName);
}
We use extension method to complete this way:
public static TOutput Switch<TOutput, TInput>(this TInput input, IEnumerable<TInput> inputSource, IEnumerable<TOutput> outputSource, TOutput defaultOutput)
{
IEnumerator<TInput> inputIterator = inputSource.GetEnumerator();
IEnumerator<TOutput> outputIterator = outputSource.GetEnumerator();
TOutput result = defaultOutput;
while (inputIterator.MoveNext())
{
if (outputIterator.MoveNext())
{
if (input.Equals(inputIterator.Current))
{
result = outputIterator.Current;
break;
}
}
else break;
}
return result;
}
The Test5 is used to call:
public static void Test5()
{
string englishName = “apple”;
string Name = englishName.Switch(
new string[] { “apple”, “orange”, “banana”, “pear” },
new string[] { “Apple”, “Orange”, “Banana”, “Pear” },
“unknown”
);
Console.WriteLine(Name);
}
It was simple and clear.
Finally, we’ll encapsulate the extension on while.
public static void While<T>(this T t, Predicate<T> predicate, Action<T> action) where T: class
{
while (predicate(t)) action(t);
}
Calling code:
public static void Test6()
{
People people = new People { Name = “Wretch” };
people.While(
p => p.WorkCount < 7,
p => p.Work()
);
people.Rest();
}
In this while extension, we only perform an Action, which is not good to improve:
public static void While<T>(this T t, Predicate<T> predicate, params Action<T>[] actions) where T : class
{
while (predicate(t))
{
foreach (var action in actions)
action(t);
}
}
Call again; we can perform multiple operations in the loop:
public static void Test7()
{
People people = new People { Name = “Wretch” };
people.While(
p => p.WorkCount < 7,
p => p.Work(),
p => p.Eat(),
p => p.Drink(),
p => p.Rest()
);
people.Rest();
}
Of course ,the previous If extension also can be like this .But here we just write one :
public static T If<T>(this T t, Predicate<T> predicate, params Action<T>[] actions) where T : class
{
if (t == null) throw new ArgumentNullException();
if (predicate(t))
{
foreach (var action in actions)
action(t);
}
return t;
}
If you don’t want to use params, you need to display a statement about a set of Action.