惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

G
Google Developers Blog
T
Troy Hunt's Blog
博客园 - 【当耐特】
N
Netflix TechBlog - Medium
V
V2EX
I
InfoQ
量子位
Hugging Face - Blog
Hugging Face - Blog
The Register - Security
The Register - Security
J
Java Code Geeks
V
Visual Studio Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
S
Security @ Cisco Blogs
爱范儿
爱范儿
Hacker News: Ask HN
Hacker News: Ask HN
Recent Commits to openclaw:main
Recent Commits to openclaw:main
B
Blog
Apple Machine Learning Research
Apple Machine Learning Research
V2EX - 技术
V2EX - 技术
罗磊的独立博客
S
Security Affairs
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
IT之家
IT之家
O
OpenAI News
W
WeLiveSecurity
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
GbyAI
GbyAI
The Hacker News
The Hacker News
Attack and Defense Labs
Attack and Defense Labs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Microsoft Azure Blog
Microsoft Azure Blog
F
Fortinet All Blogs
Schneier on Security
Schneier on Security
雷峰网
雷峰网
Scott Helme
Scott Helme
B
Blog RSS Feed
有赞技术团队
有赞技术团队
Recent Announcements
Recent Announcements
L
LangChain Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Y
Y Combinator Blog
Help Net Security
Help Net Security
NISL@THU
NISL@THU
A
About on SuperTechFans
L
LINUX DO - 最新话题
博客园 - 司徒正美
博客园 - 聂微东
博客园 - 三生石上(FineUI控件)
Spread Privacy
Spread Privacy
P
Proofpoint News Feed

博客园 - laughter

[转]VMPlayer的Briged网络配置 [转]移动互联网应用技术架构简介-Restful服务 理解WCF中的Contracts [翻译]在ASP.NET Web API中通过OData支持查询和分页 [转]NBehave行为驱动测试关于story和scenarios [转]使用TeamCity对项目进行可持续集成管理(一) [转]SpecFlow使用入门 [转]软件测试- 3 - Mock 和Stub的区别 [翻译]创建ASP.NET WebApi RESTful 服务(11) [翻译]创建ASP.NET WebApi RESTful 服务(10) [翻译]创建ASP.NET WebApi RESTful 服务(9) [转]模拟HttpContext 实现ASP.NET MVC 的单元测试 [翻译]创建ASP.NET WebApi RESTful 服务(8) [翻译]创建ASP.NET WebApi RESTful 服务(7) [转]软件开发过程(CMMI/RUP/XP/MSF)是与非? [转]比较 Rational Unified Process (RUP) 和 Microsoft Solutions Framework (MSF) [翻译]Behavior-Driven Development (BDD)行为驱动开发(二) [翻译]Behavior-Driven Development (BDD)行为驱动开发(一) 【Visual Studio2010】创建XAML分析插件
使用Using的注意事项
laughter · 2014-11-12 · via 博客园 - laughter

参数传递

C#中有四种参数类型:值类型,Ref参数,Out参数,params参数。默认参数都是以传值方式传递,这意味着方法中的变量会在内存中被分配新的存储空间,并赋值。对于引用类型,这种传值意味着传递的是实例对象在栈中的地址。

void Foo (StringBuilder x)
{
    x = null;
}

...

StringBuilder y = new StringBuilder();
y.Append ("hello");
Foo (y);
Console.WriteLine (y==null);

代码中的y不会被改变。反之,下面的代码会输出“hello world”。(注意上面赋值的概念,如果变量存在一组子成员变量,现在两个变量都指向了同一片子成员变量,那么子成员变量的变化就会影响到两个变量)

void Foo (StringBuilder x)
{
    x.Append (" world");
}

...

StringBuilder y = new StringBuilder();
y.Append ("hello");
Foo (y);
Console.WriteLine (y);

如果将参数传递方式修改为Ref,那么上面的y就会被置为null,因为传递的是变量本身而非地址。进入方法的范围时,不会再分配新的存储空间,引用被修改,栈中的地址不再指向已分配的空间。

关于Using

使用Using语句块时,可以再Using语句内定义变量,也可以在其外部定义变量。但是如下这种写法在C#中会报错:Cannot pass 'TheInt' as a ref or out argument because it is a 'using variable'

public class DisposableInt : IDisposable
{
    private int? _Value;

    public int? MyInt
    {
        get { return _Value; }
        set { _Value = value; }
    }

    public DisposableInt(int InitialValue)
    {
        _Value = InitialValue;
    }

    public void Dispose()
    {
        _Value = null;
    }
}

public class TestAnInt
{
    private void AddOne(ref DisposableInt IntVal)
    {
        IntVal.MyInt++;
    }

    public void TestIt()
    {
        DisposableInt TheInt;
        using (TheInt = new DisposableInt(1))
        {
            Console.WriteLine(String.Format("Int Value: {0}", TheInt.MyInt));
            AddOne(ref TheInt);
            Console.WriteLine(String.Format("Int Value + 1: {0}", TheInt.MyInt));
        }
    }
}

在Using语句内声明的变量全部是只读变量,这意味着在Using的语句块内不允许更改该对象的引用关系(例如,尝试赋值为null会报错)。因此,如果在此范围内使用ref或者out时会抛出编译器错误。在VB.NET中,不会直接抛出错误,但是会出现TheInt不会被修改的现象。原因在于以上的代码会被编译为(部分代码省略):

    public void TestIt()
    {
        DisposableInt TheInt =new DisposableInt(1);
         DisposableInt TheInt2 = TheInt;
         try
        {
            AddOne(ref TheInt2 );
        }
        finally
        {
        }
    }            

看到一个新的对象代替目标对象进入方法,原有的对象不会被修改。如果在AddOne的范围内出现引用被修改的情况,TheInt和TheInt2的参照关系会被修改。此时,在AddOne之后使用的TheInt实际上已经被编译器自动优化为TheInt2。

为了使用Using,可以讲代码修改为如下,此时TheInt不再是只读变量,就不会遇到此类问题:

DisposableInt theInt = new DisposableInt(1);
using (theInt)
{
    AddOne(ref theInt);
}