LINQ To SQL深入学习系列之二(C#3.0为LINQ的加强之二)

简介:

本文大部分内容整理自msdn

 

3、分部方法

 

分部方法使类的某个部分的实施者能够定义方法(类似于事件)。类的另一部分的实施者可以决定是否实现该方法。如果未实现该方法,编译器将移除方法签名以及对该方法的所有调用。因此,分部类中的任何代码都可以随意地使用分部方法,即使未提供实现也是如此。如果调用了未实现的方法,将不会导致编译时错误或运行时错误。

在自定义生成的代码时,分部方法特别有用。这些方法允许保留方法名称和签名,因此生成的代码可以调用方法,而开发人员可以决定是否实现方法。与分部类非常类似,分部方法使代码生成器创建的代码和开发人员创建的代码能够协同工作,而不会产生运行时开销。

分部方法声明由两个部分组成:定义和实现。它们可以位于分部类的不同部分中,也可以位于同一部分中。

 

复制代码
namespace  PM
{
    
partial   class  A
    {
        
partial   void  OnSomethingHappened( string  s);
    }

    
//  This part can be in a separate file.
     partial   class  A
    {
        
//  Comment out this method and the program
        
//  will still compile.
         partial   void  OnSomethingHappened(String s)
        {
            Console.WriteLine(
" Something happened: {0} " , s);
        }
    }
}
复制代码

 

要点:

 

1、分部方法声明必须以上下文关键字 partial 开头,并且方法必须返回 void。

2、分部方法可以有 ref 参数,但不能有 out 参数。

3、分部方法为隐式 private 方法,因此不能为 virtual 方法。

4、分部方法不能为 extern 方法,因为主体的存在确定了方法是在定义还是在实现。

5、分部方法可以有 static 和 unsafe 修饰符。

6、分部方法可以为泛型的。约束将放在定义分部方法声明上,但也可以选择重复放在实现声明上。参数和类型参数名称在实现声明和定义声明中不必相同。

7、不能将委托转换为分部方法。

 

场景举例:轻量级事件处理

  有的时候,自动生成的代码需要事件这类语言构造来通知用户对某些操作进行处理,但实际上用于编写的代码就位于自动生成的类型之中。此时,或者需要触发一个事件,或者就需要生成一个virtual方法来让用户继承。但无论是事件还是继承,开销都是比较大的,所以可以通过分部方法来实现轻量级的处理方式。如下面的类:

 

复制代码
  partial   class  Customer
    { 
        
string  name; 
        
public   string  Name 
        { 
            
get  
            { 
                
return  name; 
            } 
            
set  
            { 
                OnBeforeUpdateName(); 
                OnUpdateName(); 
                name 
=  value; 
                OnAfterUpdateName(); 
            } 
        } 
        
partial   void  OnBeforeUpdateName(); 
        
partial   void  OnAfterUpdateName(); 
        
partial   void  OnUpdateName(); 
    } 
复制代码

 

 这里定义了三个分部方法,其意义不言而喻。假设这是系统自动生成的代码,则我们只需在另外一个源代码文件中的partial class Customer中实现这几个分部方法即可。

另外在自定义DataContext中的Insert、Update、Delete方法也会用到分部类,等我们讲到DataContext时再详细讲解这部分。

 

4、扩展方法:


扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。扩展方法是一种特殊的静态方法,调用扩展方法与调用在类型中实际定义的方法之间没有明显的差异。扩展方法是可以通过使用实例方法语法调用的静态方法。效果上,使得附加的方法扩展已存在类型和构造类型成为可能。他可以对现有类功能进行扩充,从而使该类型的实例具有更多的方法。扩展方法有助于把今天动态语言中流行的对快速录入支持的灵活性,与强类型语言之性能和编译时验证融合起来。这里先举一个msdn中的例子:
下面的示例演示为 System.String 类定义的一个扩展方法。假设我要分析一个字符串,希望得到字符串中单词的个数,一般情况下我们可能使用一个统计的函数来解决这个问题

 

复制代码
static   void  Main( string [] args)
        {
           
            
string  s  =   " Hello Extension Methods " ;
            Console.WriteLine(WordCount(s));         
        }
        
static   int  WordCount( string  str)
        {
            
return  str.Split( new   char [] {  '   ' ' . ' ' ? '  }, StringSplitOptions.RemoveEmptyEntries).Length;

        }
复制代码

但这样用起来感觉上可能会很别扭,这个WordCount方法如果就是字符串类中的一个方法多好,像所有字符串的实例方法一样用。这里我们引出扩展方法来解决这个问题。

 

 

复制代码
namespace  ExtensionMethods
{
    
public   static   class  MyExtensions
    {
        
public   static   int  WordCount( this  String str)
        {
            
return  str.Split( new   char [] {  '   ' ' . ' ' ? '  }, StringSplitOptions.RemoveEmptyEntries).Length;
        }
    }   
}
复制代码

 

注意,上面的静态方法在第一个类型是string的参数变量前有个“this”关键词,这告诉编译器,这个特定的扩展方法应该添加到类型为“string”的对象中去。
使用 using 指令将 WordCount 扩展方法放入范围中:
using ExtensionMethods;

 

 

string  s  =   " Hello Extension Methods " ;
int  i  =  s.WordCount();

 

扩展方法要点 
1、扩展方法的本质为将实例方法调用在编译期改变为静态类中的静态方法调用。事实上,它确实拥有静态方法所具有的所有功能。 
2、通常,您更多时候是调用扩展方法而不是实现您自己的扩展方法。由于扩展方法是使用实例方法语法调用的,因此不需要任何特殊知识即可从客户端代码中使用它们。若要为特定类型启用扩展方法,只需为在其中定义这些方法的命名空间添加 using 指令。
3、扩展方法的优先级:现有实例方法优先级最高,其次为最近的namespace下的静态类的静态方法,最后为较远的namespace下的静态类的静态方法。(与接口或类方法具有相同名称和签名的扩展方法永远不会被调用 )
4、在代码中,可以使用实例方法语法调用该扩展方法。但是,编译器生成的中间语言 (IL) 会将代码转换为对静态方法的调用。因此,并未真正违反封装原则。实际上,扩展方法无法访问它们所扩展的类型中的私有变量。

 

扩展方法通用准则 
1、通常,建议您只在不得已的情况下才实现扩展方法,并谨慎地实现。只要有可能,必须扩展现有类型的客户端代码都应该通过创建从现有类型派生的新类型来达到这一目的。
2、在使用扩展方法来扩展您无法更改其源代码的类型时,您需要承受该类型实现中的更改会导致扩展方法失效的风险。
3、如果您确实为给定类型实现了扩展方法,请记住以下两点:
     如果扩展方法与该类型中定义的方法具有相同的签名,则扩展方法永远不会被调用。
     扩展方法被在命名空间级别放入范围中。例如,如果您在同一个名为 Extensions 的命名空间中具有多个包含扩展方法的静态类,则这些扩展方法将全部由 using Extensions; 指令放入范围中。

 


本文转自 你听海是不是在笑 博客园博客,原文链接:http://www.cnblogs.com/nuaalfm/archive/2008/08/07/1262711.html  ,如需转载请自行联系原作者


相关文章
|
12天前
|
开发框架 自然语言处理 .NET
C#一分钟浅谈:LINQ 查询表达式的使用技巧
【9月更文挑战第6天】LINQ(Language Integrated Query)是C#开发中的强大工具,使查询数据集合变得简单且接近自然语言。本文从基础入手,通过具体示例讲解LINQ查询表达式的使用技巧,包括过滤、排序和分组等操作。同时,文章还探讨了常见问题及解决方法,如性能优化、过早枚举和类型转换等,帮助开发者写出更高效、易维护的代码。
52 15
|
10天前
|
Linux C# 开发者
Uno Platform 驱动的跨平台应用开发:从零开始的全方位资源指南与定制化学习路径规划,助您轻松上手并精通 C# 与 XAML 编程技巧,打造高效多端一致用户体验的移动与桌面应用程序
【9月更文挑战第8天】Uno Platform 的社区资源与学习路径推荐旨在为初学者和开发者提供全面指南,涵盖官方文档、GitHub 仓库及社区支持,助您掌握使用 C# 和 XAML 创建跨平台原生 UI 的技能。从官网入门教程到进阶技巧,再到活跃社区如 Discord,本指南带领您逐步深入了解 Uno Platform,并提供实用示例代码,帮助您在 Windows、iOS、Android、macOS、Linux 和 WebAssembly 等平台上高效开发。建议先熟悉 C# 和 XAML 基础,然后实践官方教程,研究 GitHub 示例项目,并积极参与社区讨论,不断提升技能。
29 2
|
26天前
|
SQL 存储 关系型数据库
PostgreSQL核心之SQL基础学习
PostgreSQL核心之SQL基础学习
23 3
|
1月前
|
开发框架 .NET API
C#/.NET/.NET Core推荐学习书籍(24年8月更新)
C#/.NET/.NET Core推荐学习书籍(24年8月更新)
|
2月前
|
SQL 存储 关系型数据库
关系型数据库SQL Server学习
【7月更文挑战第4天】
48 2
|
3月前
|
SQL 存储 Java
SQL数据库学习指南:从基础到高级
SQL数据库学习指南:从基础到高级
|
3月前
|
SQL 数据库
零基础学习数据库SQL语句之操作表中数据的DML语句
零基础学习数据库SQL语句之操作表中数据的DML语句
40 0
零基础学习数据库SQL语句之操作表中数据的DML语句
|
2月前
|
Dart 算法 JavaScript
C#数据结构与算法入门教程,值得收藏学习!
C#数据结构与算法入门教程,值得收藏学习!
|
2月前
|
SQL 关系型数据库 MySQL
sql 学习
sql 学习
|
2月前
|
SQL 存储 Java
SQL数据库学习指南:从基础到高级
SQL数据库学习指南:从基础到高级