探究委托的如何实现非静态方法

在C#里面对于委托的如何加载非静态方法一直都很疑惑,自己对于非静态方法的认识来看,如果要安全的实现非静态方法必须引用实例里面的
字段,经过查阅资料,知道委托类里面有一个_target字段如果是委托的是静态方法值为零,如果委托是非静态为会自动寻找方法的实例,
说的很模糊,这个_target字段应该是一个object型,但是里面地址指向的什么。我先在程序上声明一个类有两个字段这两个字段一个为static
一个非static,有两个方法一个静态一个非静态,我在方法里面对类的方法进行操作,看看对实例有什么影响。

public delegate void testChangeDelegate();
  public class testChange
    {
        public int notStaticInt;
        public static int staticInt;
  public static void staticinWay()
        {
            textStruct tt = new textStruct();
Console.WriteLine("静态方法之前{0}", staticInt);
            staticInt += 1;

            Console.WriteLine("静态方法之后{0}", staticInt);

        }
        public void notStaticWay()
        {
            textStruct tt = new textStruct();
            Console.WriteLine("非静态方法之前{0}", notStaticInt);
            notStaticInt += 1;

            Console.WriteLine("非静态方法之后{0}", notStaticInt);
        }

    }

然后再main函数里面写下

static void Main(string[] args)
        {
            //委托的方法使用会改变原有实例的值测验
             testChange tt = new testChange();
            testChangeDelegate ttc = new testChangeDelegate(tt.notStaticWay);
            ttc += tt.notStaticWay;
            ttc += testChange.staticinWay;
            ttc += testChange.staticinWay;
            ttc();
            Console.WriteLine(tt.notStaticInt);
            Console.WriteLine(testChange.staticInt);
}

输出结果为

静态方法之前0
静态方法之后1
静态方法之前1
静态方法之后2
非静态方法之前0
非静态方法之后1
非静态方法之前1
非静态方法之后2
非静态字段为2
静态字段为2

  

从结果看如果是非静态方法,_target中的实例就是原来声明类中的实例
但是当我将类声明成struct时(就是将public class testChange改成 public struct testChange),我再次运行程序。
输出结果为

非静态方法之前0
非静态方法之后1
非静态方法之前0
非静态方法之后1
静态方法之前0
静态方法之后1
静态方法之前1
静态方法之后2
非静态字段为0
静态字段为2

同一个结构实例可是实例字段并没有被非静态方法改变,只是在运行时改变了,看来_target中的实例地址并不是原来struct tt的,
应该是将tt复制后,然后装箱成object将t地址赋给_target,但是复制有三种情况一种是浅层复制,一种是深层复制,一种是普通复制
直接将地址赋过去,会是哪种呢?(关于浅层复制和深层复制参照······)
首先思考上面的结果如果是深层复制上面无论是类还是结构结果都一样,现在就是判断是直接赋原对象地址的普通复制还是浅层复制
于是我修改testChange类将其修改成这样,我在类中添加了一个结构体,如果是普通复制结构体前后的静态字段和非静态字段与外面的类相同,如果是浅层
复制的话结构体里面的结果同上面结构testChange相同

public delegate void testChangeDelegate();
    public class testChange
    {
        public int notStaticInt;
        public static int staticInt;
        public struct textStruct
        {
            public int notStaticInt;
            public static int staticInt;
        }
        public static void staticinWay()
        {
            textStruct tt = new textStruct();
            Console.WriteLine("方法之前{0} {1}", staticInt,tt.notStaticInt);
            staticInt += 1;
            tt.notStaticInt += 1;
            Console.WriteLine("方法之后{0} {1}", staticInt, tt.notStaticInt);

        }
        public void notStaticWay()
        {
            textStruct tt = new textStruct();
            Console.WriteLine("方法之前{0} {1}", notStaticInt,tt.notStaticInt);
            notStaticInt += 1;
            tt.notStaticInt += 1;
            Console.WriteLine("方法之后{0} {1}", notStaticInt, tt.notStaticInt);
        }

    }
}
   testChange tt = new testChange();
            testChangeDelegate ttc = new testChangeDelegate(tt.notStaticWay);
            ttc += tt.notStaticWay;
            ttc += testChange.staticinWay;
            ttc += testChange.staticinWay;
            ttc();
            Console.WriteLine(tt.notStaticInt);
            Console.WriteLine(testChange.staticInt);
            Console.WriteLine(tt.tt.notStaticInt);
            Console.WriteLine(testChange.textStruct.staticInt);

结果是

方法之前0 1
方法之后1 1
方法之前1 0
方法之后2 1
方法之前0 0
方法之后1 1
方法之前1 1
方法之后2 2
2
2
0
2

将类改成结构后
结果是

方法之前0 1
方法之后1 1
方法之前0 0
方法之后1 1
方法之前0 0
方法之后1 1
方法之前1 1
方法之后2 2
0
2
0
2

从结果看结构体tt的结果同上面结构体testChange相同,分析可知是浅层复制。

这样看来.net framework在后台给实例方法复制对象时采用的是浅层复制,而不是直接引用地址。

时间: 2024-08-09 06:42:37

探究委托的如何实现非静态方法的相关文章

静态方法中调用非静态方法

静态static方法中不能调用非静态non-static方法,准确地说是不能直接调用non-static方法.但是可以通过将一个对象的引用传入static方法中,再去调用该对象的non-static方法. 在主函数(static方法)中我们经常创建某个类的实例,再利用其引用变量调用它的非静态方法. //StaticMethodTest.java//A ststic method cannot call a non-static method, but we can transfer a obje

一个Activity调用另一个Activity的非静态方法

注意:前提是界面二被打开过未关闭,则用此方法即可实现在界面一中调用界面二的方法! 界面一: public class OneActivity extends Activity { @Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_one); callTwoActivityMethod(); } /

静态方法加锁,和非静态方法加锁区别

今天看了到有意思的题:在静态方法上加锁 和 非静态方法加锁 有什么区别,从而再次引出锁机制的一些理解. 先看方法: // 这是一个很简单的类,里面共享静态变量 num,然后一个静态 和 非静态方法,都加上锁 // 我们假设有两个线程同时操作这两个方法,那么数据能互斥吗? Java代码   public class Walk { public static int num = 100; public static Walk walk = new Walk(); // 静态 public synch

C#中静态与非静态方法比较

C#静态方法与非静态方法的区别不仅仅是概念上的,那么他们有什么具体的区别呢?让我们通过本文向你做一下解析. C#的类中可以包含两种方法:C#静态方法与非静态方法.那么他们的定义有什么不同呢?他们在使用上会有什么不同呢? 让我们来看看最直观的差别:使用了static 修饰符的方法为静态方法,反之则是非静态方法. 下面我们分四个方面来看看C#静态方法与非静态方法的差异: C#静态方法与非静态方法比较一.C#静态成员: ①静态成员属于类所有,非静态成员属于类的实例所有. ②每创建一个类的实例,都会在内

C#静态方法与非静态方法比较

c#静态方法与非静态方法比较: 一.静态方法:使用static修改的方法就是静态方法,否则就是非静态方法. 二.差异比较: 第一:C#静态成员:(1)静态成员属于类所有,非静态成员属于类的实例所有. (2)每创建一个类的实例,都会在内存中为非静态成员新分配一块存储. 总结:静态成员属于类所有,为各个类的实例所公用,无论类创建了多少实例,类的静态成员在内存中只占同一块区域.   第二:C#静态方法:     (1)C#静态方法属于类所有,类实例化前即可使用. (2)非静态方法可以访问类中的任何成员

c#静态方法和非静态方法详细介绍

C#的类中可以包含两种方法:静态方法和非静态方法. 使用了static 修饰符的方法为静态方法,反之则是非静态方法. 静态方法是一种 特殊的成员方法,它不属于类的某一个具体的实例,而是属于类本身. 所以对静态方法不需要 首先创建一个类的实例,而是采用类名.静态方法的格式 . 1.static方法是类中的一个成员方法,属于整个类,即不用创建任何对象也可以直接调用! static内部只能出现static变量和其他static方法!而且static方法中还不能使用this....等关键字..因为它是

静态方法与非静态方法的区别

转自:http://joe5456536.blog.163.com/blog/static/8537477320117136658629/ http://www.cnblogs.com/devinzhang/archive/2012/04/27/2473570.html 我知道静态变量的使用要很小心,因为它在每个对象中是共享的.但是对于静态方法我的认识只局限于下面: ● 生命周期(Lifecycle): 静态方法(Static Method)与静态成员变量一样,属于类本身,在类装载的时候被装载到

PHP中静态方法(static)与非静态方法的使用及区别

static关键字用来修饰属性.方法,称这些属性.方法为静态属性.静态方法. static关键字声明一个属性或方法是和类相关的,而不是和类的某个特定的实例相关,因此,这类属性或方法也称为"类属性"或"类方法" 如果访问控制权限允许,可不必创建该类对象而直接使用类名加两个冒号"::"调用. static关键字可以用来修饰变量.方法. 不经过实例化,就可以直接访问类中static的属性和static的方法. static 的属性和方法,只能访问sta

接口,构造器与垃圾回收机制,对像的生命周期。非静态方法与静态方法。

java不充许多继承是,为了避免“致命方块”的出现例如 B继承A,C继承A. C和C里面都有play()方法 .现在D继承了B,C 想想D.play()调用 的是哪个play()呢,这就是问题所在. 所以java提供了接口来解决此问题. 问:接口并不是真正的多重继承,因为你无法在它里面实现程序代码,不是吗?如果是这样,那还要接口做什么? 答:多态,多态,多态.接口有无比的适用性,若你以接口取代具体的子类或抽象的父类作为参数或返回类型,则你就可以传入任何有实现该接口的东西.这么说吧,使用接口你就可