zoukankan      html  css  js  c++  java
  • 使用Using的注意事项

    参数传递

    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);
    }
  • 相关阅读:
    MVVM知识库总结
    C#常用类汇总
    silverlight调用MVC WebApi方法
    IE调试方法(一)<转>
    PHP中关于超链接的拼接问题
    intval()和(int)转换使用与区别
    ThinkPHP模板(一)
    修改ThinkSNS网站入口
    js中的this和apply
    Thinkphp的Volist标签
  • 原文地址:https://www.cnblogs.com/tukzer/p/4091467.html
Copyright © 2011-2022 走看看