Extension methods
[索引页]
今天看一篇写得很好的关于Extension methods方法的文章:
为大家翻译过来,谢谢来访.
例如,System.String class是被编译成.NET Framework 的sealed类.我们不能继承这个String class,并且我们不能改变这个String类和在这个framework中重新编译.在过去,我们能将我们使用的方法分类包装在一个静态类中.如下面:
我们在String class中显示一个ToDouble方法.当一个方法的第一个参数包括this 符号,这个方法是一个extension method.我们必须在extension methods中定义一个 non-generic, static class,将像StringExtensions类.
StringExtensions类中我们定义两个extension 方法.我们现调用它既能使用实例来调用这个方法也能如下面,如果这个方法是System.String的成员,我们不需要使用这个staic class 名.
不管外观,extension methods不是这个类型的成员,是被扩充出来的.特别,这个ToDouble我们是利用在其他类型中的静态方法,当这个C#编译器能隐藏这个事实.更重要的是它实现了扩展方法而没有打破的我们访问目标对象成员的习惯,我在使用extension方法时不能发访问目标对象的protected和private成员.
Extension Method 带来的革命
一个Extension Method能在任何对象实例上调用,只要我们改变这个方法的第一个参数的类型.如,下面扩展方法转化IList这样就能被任何对象利用.
在上面我们在字符串数组中使用这个扩展方法,就是在一个数组中显示IList接口.注意我们需要检测null,如他能合法的在一个程序为一个null对象引用调用extension method.
一个Extension Method不能被重写或隐藏任何实例本身的方法.例如,如果我们定义一个ToString extentsion method,这个扩展方法不能被调用,因为每一个对象已经有一个ToString方法.编译器他只绑定一个方法当它不能找到适合的实例方法签名时他才帮定extension方法!
一个Extension Method只使用在当你导入命名空间中包括有定义这个extensioni method的静态类.尽管你能永远通过调用这个extension method的命名空间的类名的方式(如Foo.StringExtensions.ToDouble()),但没有一个机制让你使用实例调用的语法搜索一个单独的extension method,除非你导入命名空间.一旦导入命名空间,在这个命名空间中的所有的扩展方法都被定义了.还有另外一个当设计命名空间时候你应该小心扩展方法的范围.
Extension Methods and LINQ
LINQ在System.Linq namespace中定义很多扩展方法.这些扩展方法都是分别扩展于IEnumerable<T> 和 IQueryable<T> 实现标准的查询操作符,如Where, Select, OrderBy,和更多.例如当我们包括System.Linq namespace,我们能使用Where扩展方法去过滤一个enumerable collection of items.
上面这个和Where的定义很像:
就如你看到的,Where的第二个参数的类型为Func<TSource,bool>.这个参数是一个"predicate"(MSDN是"谓词"),一个predicate是一个函数,在Where方法能被调用后去测试每一个元素,如果predicate返回true,这个元素就包括在结果集中,否则这个元素被排除.刚才写到---不同的LINQ to SQL提供者是一个IQueryable<T>数据源.这个提供者会分析这个predicate去为SQL命令构建一个WHERE clause并发送到数据库..但更多动作在这之后会写到
原文地址
worksguo
今天看一篇写得很好的关于Extension methods方法的文章:
为大家翻译过来,谢谢来访.
例如,System.String class是被编译成.NET Framework 的sealed类.我们不能继承这个String class,并且我们不能改变这个String类和在这个framework中重新编译.在过去,我们能将我们使用的方法分类包装在一个静态类中.如下面:
// Extending string via static methods (pre C# 3.0)
public static class StringUtils
{
static public double ToDouble(string data)
{
double result = double.Parse(data);
return result;
}
}
public static class StringUtils
{
static public double ToDouble(string data)
{
double result = double.Parse(data);
return result;
}
}
// Usage:
string text = "43.35";
double data = StringUtils.ToDouble(text);
string text = "43.35";
double data = StringUtils.ToDouble(text);
我们在String class中显示一个ToDouble方法.当一个方法的第一个参数包括this 符号,这个方法是一个extension method.我们必须在extension methods中定义一个 non-generic, static class,将像StringExtensions类.
// extending String via extension methods
public static class StringExtensions
{
static public double ToDouble(this string data)
{
double result = double.Parse(data);
return result;
}
static public int ToInt32(this string data)
{
int result = Int32.Parse(data);
return result;
}
}
public static class StringExtensions
{
static public double ToDouble(this string data)
{
double result = double.Parse(data);
return result;
}
static public int ToInt32(this string data)
{
int result = Int32.Parse(data);
return result;
}
}
StringExtensions类中我们定义两个extension 方法.我们现调用它既能使用实例来调用这个方法也能如下面,如果这个方法是System.String的成员,我们不需要使用这个staic class 名.
string text = "43.35";
double data = text.ToDouble();
double data = text.ToDouble();
不管外观,extension methods不是这个类型的成员,是被扩充出来的.特别,这个ToDouble我们是利用在其他类型中的静态方法,当这个C#编译器能隐藏这个事实.更重要的是它实现了扩展方法而没有打破的我们访问目标对象成员的习惯,我在使用extension方法时不能发访问目标对象的protected和private成员.
Extension Method 带来的革命
一个Extension Method能在任何对象实例上调用,只要我们改变这个方法的第一个参数的类型.如,下面扩展方法转化IList这样就能被任何对象利用.
public static class IListExtensions
{
public static void Randomize<T>(this IList<T> input)
{
if (input == null)
return;
for (int i = input.Count - 1; i > 0; i--)
{
int n = rand.Next(i + 1);
T temp = input[i];
input[i] = input[n];
input[n] = temp;
}
}
static Random rand = new Random();
}
{
public static void Randomize<T>(this IList<T> input)
{
if (input == null)
return;
for (int i = input.Count - 1; i > 0; i--)
{
int n = rand.Next(i + 1);
T temp = input[i];
input[i] = input[n];
input[n] = temp;
}
}
static Random rand = new Random();
}
在上面我们在字符串数组中使用这个扩展方法,就是在一个数组中显示IList接口.注意我们需要检测null,如他能合法的在一个程序为一个null对象引用调用extension method.
void RandomizeArray()
{
string[] cities = { "Boston", "Los Angeles",
"Seattle", "London", "Hyderabad" };
cities.Randomize();
foreach (string city in cities)
{
Console.WriteLine(city);
}
}
{
string[] cities = { "Boston", "Los Angeles",
"Seattle", "London", "Hyderabad" };
cities.Randomize();
foreach (string city in cities)
{
Console.WriteLine(city);
}
}
一个Extension Method不能被重写或隐藏任何实例本身的方法.例如,如果我们定义一个ToString extentsion method,这个扩展方法不能被调用,因为每一个对象已经有一个ToString方法.编译器他只绑定一个方法当它不能找到适合的实例方法签名时他才帮定extension方法!
一个Extension Method只使用在当你导入命名空间中包括有定义这个extensioni method的静态类.尽管你能永远通过调用这个extension method的命名空间的类名的方式(如Foo.StringExtensions.ToDouble()),但没有一个机制让你使用实例调用的语法搜索一个单独的extension method,除非你导入命名空间.一旦导入命名空间,在这个命名空间中的所有的扩展方法都被定义了.还有另外一个当设计命名空间时候你应该小心扩展方法的范围.
Extension Methods and LINQ
LINQ在System.Linq namespace中定义很多扩展方法.这些扩展方法都是分别扩展于IEnumerable<T> 和 IQueryable<T> 实现标准的查询操作符,如Where, Select, OrderBy,和更多.例如当我们包括System.Linq namespace,我们能使用Where扩展方法去过滤一个enumerable collection of items.
private static void UseWhereExtensionMethod()
{
string[] cities = { "Boston", "Los Angeles",
"Seattle", "London", "Hyderabad" };
IEnumerable<string> filteredList =
cities.Where(delegate(string s) { return s.StartsWith("L"); });
// filteredList will include only London and Los Angeles
}
{
string[] cities = { "Boston", "Los Angeles",
"Seattle", "London", "Hyderabad" };
IEnumerable<string> filteredList =
cities.Where(delegate(string s) { return s.StartsWith("L"); });
// filteredList will include only London and Los Angeles
}
上面这个和Where的定义很像:
namespace System.Linq
{
public static class Enumerable
{
//
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate)
{
//
}
// ..
}
}
{
public static class Enumerable
{
//
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate)
{
//
}
// ..
}
}
就如你看到的,Where的第二个参数的类型为Func<TSource,bool>.这个参数是一个"predicate"(MSDN是"谓词"),一个predicate是一个函数,在Where方法能被调用后去测试每一个元素,如果predicate返回true,这个元素就包括在结果集中,否则这个元素被排除.刚才写到---不同的LINQ to SQL提供者是一个IQueryable<T>数据源.这个提供者会分析这个predicate去为SQL命令构建一个WHERE clause并发送到数据库..但更多动作在这之后会写到
原文地址
worksguo