c# 静太函数访问类成员
2016-01-07 11:10:56 mps1651 阅读数 390

1.public

public属性的成员,访问不受限,容易理解,不必多说;

2.protected

protected属性的成员,访问仅限于此类和从此类派生的类;

3.private

private属性的成员,访问仅限于此类访问;

4.internal

internal属性的成员,访问仅限于此程序;

着重区分一下protected和private两者,举例来说:

    class BaseTest
    {
        public int a = 1;
        protected int b = 2;
        internal int aa = 3;
        private int bb = 4;

        public void print()
        {
            BaseTest test = new BaseTest();
            Console.WriteLine("Print Member a : {0} , b : {1} , aa : {2} , bb : {3}", test.a, test.b, test.aa, test.bb); // 此处可正确访问
        }
    }

    class Program:BaseTest
    {
        public int c;
        public int d;
        public int cc;
        public int dd;

        public void init()
        {
            BaseTest bstest = new BaseTest();
            this.c = bstest.a;
            this.d = bstest.b;  // 此处会发生报错,基类对象无法访问基类protected成员b
        }

        static void Main(string[] args)
        {
            Program pm = new Program();
            BaseTest bstest = new BaseTest();
            pm.c = bstest.a;
            pm.d = bstest.b;  // 此处发生报错,提示错误同上
            pm.d = pm.b;       // 此处可正确访问
            pm.cc = bstest.bb;  // 此处发生报错,基类private成员bb不可访问
        }
    }

如上代码中所示,protected成员只能在基类中(此处与private成员受限及其相似)、或者派生类中通过派生类对象进行访问。

2006-01-07 13:26:00 calm_agan 阅读数 798

数据成员

       常数

       字段

              只读字段:

              读写字段

       事件

函数成员

       方法

       构造器

              类型构造器

              对象构造器

       属性

              无参属性

              有参属性(索引器)

       操作符

              转换操作符

              重载操作符

2018-10-08 01:08:00 weixin_33889245 阅读数 25
  • 常量 与类关联的常量值
  • 字段 类的变量
  • 方法 类可执行的计算和操作
  • 属性 与读写类的命名属性相关联的操作
  • 索引器 与以数组方式索引类的实例相关联的操作
  • 事件 可由类生成的通知
  • 运算符 类所支持的转换和表达式运算符
  • 构造函数 初始化类的实例或类本身所需的操作
  • 析构函数 在永久丢弃类的实例之前执行的操作
  • 类型 类所声明的嵌套类型

字段

什么是字段

  • 字段field是一种表示与对象或类型(类与结构体)关联的变量
  • 字段是类型的成员,旧称“成员变量”
  • 与对象关联的字段亦称为“实例字段”
  • 与类型关联的字段称为“静态字段”,由static修饰。

范例:C语言中的成员变量

$ vim field.c
#include <stdio.h>
// 结构体的字段
struct User
{
    int ID;
    char* UserName;
};

void main()
{
    struct User user;
    user.ID = 1;
    user.UserName = "Mr.Okay";
    printf("User #%d is %s", user.ID, user.UserName);
}
$ gcc field.c -o field.exe
$ field.exe
User #1 is Mr.Okay

实例:实例字段
通过静态变量表现实例变量当前的状态

using System;
using System.Collections.Generic;

namespace Test
{
    class User
    {
        //实例字段
        public int Age;
        public int Score;
        //静态字段
        public static int AverageAge;
        public static int AverageScore;
        public static int Amount;
        //构造函数
        public User()
        {
            User.Amount++;
        }
        //静态方法
        public static void ReportAmount()
        {
            Console.WriteLine(User.Amount);
        }
        public static void ReportAge()
        {
            Console.WriteLine(User.AverageAge);
        }
        public static void ReportScore()
        {
            Console.WriteLine(User.AverageScore);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            List<User> userlist = new List<User>();
            for(int i=0; i<100; i++)
            {
                User user = new User();
                user.Age = i;
                user.Score = i;
                userlist.Add(user);
            }

            int totalAge = 0;
            int totalScore = 0;
            foreach(var user in userlist)
            {
                totalAge += user.Age;
                totalScore += user.Score;
            }

            User.AverageAge = totalAge / User.Amount;
            User.AverageScore = totalScore / User.Amount;

            //静态变量
            User.ReportAmount();
            User.ReportAge();
            User.ReportScore();

            Console.ReadKey();
        }
    }
}

字段的声明

  • 尽管字段声明带有分号但它不是语句
  • 字段的名字一定是名词

字段的初始化

  • 无显式初始化时,字段获得其类型的默认值,所以字段永远不会未被初始化。
  • 实例字段初始化的时机是在对象创建时
  • 静态字段初始化的时机是在类型被加载load

只读字段

  • 实例只读字段
using System;
using System.Collections.Generic;

namespace Test
{
    class User
    {
        //只读实例字段
        public readonly int ID;
        //实例字段
        public int Age;
        public int Score;
        //静态字段
        public static int AverageAge;
        public static int AverageScore;
        public static int Amount;
        //构造函数
        public User(int id)
        {
            this.ID = id;//只读字段只能在实例化时初始化,且不能赋值。
            User.Amount++;
        }
        //静态方法
        public static void ReportAmount()
        {
            Console.WriteLine(User.Amount);
        }
        public static void ReportAge()
        {
            Console.WriteLine(User.AverageAge);
        }
        public static void ReportScore()
        {
            Console.WriteLine(User.AverageScore);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            List<User> userlist = new List<User>();
            for(int i=0; i<100; i++)
            {
                User user = new User(i);
                user.Age = i;
                user.Score = i;
                userlist.Add(user);
            }

            int totalAge = 0;
            int totalScore = 0;
            foreach(var user in userlist)
            {
                totalAge += user.Age;
                totalScore += user.Score;
            }

            User.AverageAge = totalAge / User.Amount;
            User.AverageScore = totalScore / User.Amount;

            //静态变量
            User.ReportAmount();
            User.ReportAge();
            User.ReportScore();

            Console.ReadKey();
        }
    }
}
  • 静态只读字段
using System;

namespace Test
{
    struct Color
    {
        public int Red;
        public int Green;
        public int Blue;
    }
    class Brush
    {
        //public static readonly Color DefaultColor = new Color()
        //{
        //    Red = 0,
        //    Green = 0,
        //    Blue = 0
        //};
        
        //静态只读构造器
        public static readonly Color DefaultColor;
        static Brush()
        {
            Brush.DefaultColor = new Color()
            {
                Red = 0,
                Green = 0,
                Blue = 0
            };
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Brush.DefaultColor.Red);
            Console.WriteLine(Brush.DefaultColor.Green);
            Console.WriteLine(Brush.DefaultColor.Blue);

            Console.ReadKey();
        }
    }
}

属性

什么是属性

  • 属性property是一种用于访问对象或类型的特征的成员,特征反映了状态
  • 属性是字段的自然扩展
    从命名上看field字段更加偏向于实例对象在内存中的布局,property属性更加偏向于反映现实世界对象的特征。
    属性对外暴露数据,数据可以是存储在字段里的,也可以是动态计算出来的。
    属性对内则保护字段不被非法值污染
using System;

namespace Test
{
    class User
    {
        private int age;
        public int GetAge()
        {
            return age;
        }
        public void SetAge(int value)
        {
            if(value >= 0 && value <= 120)
            {
                this.age = value;
            }
            else
            {
                throw new Exception("Age value has error");
            }
        }                    
    }
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                User user1 = new User();
                user1.SetAge(20);
                User user2 = new User();
                user2.SetAge(200);
                int avgAge = (user1.GetAge() + user2.GetAge()) / 2;
                Console.WriteLine(avgAge);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            Console.ReadKey();
        }
    }
}
  • 属性由getset方法进化而来
using System;

namespace Test
{
    class User
    {
        //属性 
        private int age;
        public int Age {
            get
            {
                return this.age;
            }
            set
            {
                if (value >= 0 && value <= 120)
                {
                    this.age = value;
                }
                else
                {
                    throw new Exception("Age value has error");
                }
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                User user1 = new User();
                user1.Age = 20;
                User user2 = new User();
                user2.Age = 200;
                int avgAge = (user1.Age + user2.Age) / 2;
                Console.WriteLine(avgAge);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            Console.ReadKey();
        }
    }
}
  • 属性背后的秘密

属性的声明

  • 属性完整的声明 - 后台成员变量与访问器
  • 属性简略声明 - 只有访问器
  • 动态计算值的属性
  • 注意实例属性和静态属性
  • 属性的名字一定是名词
  • 只读属性即只有getter而没有setter方法
    尽管语法上正确,几乎没有人使用只写属性,因为属性的主要目的是通过向外暴露数据而表示对象或类型的状态。
using System;

namespace Test
{
    class User
    {
        private static int amount;
        public static int Amount
        {
            get { return amount; }
            set {
                if(value >= 0)
                {
                    User.amount = value;
                }
                else
                {
                    throw new Exception("Amount value is error");
                }
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                User.Amount = 200;
                Console.WriteLine(User.Amount);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            Console.ReadKey();
        }
    }
}

VS2017中书写属性的,类中键入propfull后连续按两下Tab键,即可快速书写settergetter方法。

属性与字段的关系

  • 一般情况下,属性和字段都用于表示实体(对象或类型)的状态
  • 属性大多数情况下是字段的包装器wrapper
  • 建议永远使用属性而非字段来暴露数据,即字段永远都是privateprotected的。

索引器

什么是索引器
索引器(indexer)是一种成员:使对象能够用与数组相同的方式即是用下标进行索引

索引器的声明
注意:没有静态索引器

using System;
using System.Collections.Generic;

namespace Test
{
    class User
    {
        private Dictionary<string, int> dict = new Dictionary<string, int>();
        public int? this[string key]
        {
            get
            {
                if(this.dict.ContainsKey(key))
                {
                    return this.dict[key];
                }
                else
                {
                    return null;
                }
            }
            set
            {
                if (value.HasValue == false)
                {
                    throw new Exception("dict cannot be null");
                }
                else
                {
                    if (this.dict.ContainsKey(key))
                    {
                        this.dict[key] = value.Value;
                    }
                    else
                    {
                        this.dict.Add(key, value.Value);
                    }
                }
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            User user = new User();
            user["ID"] = 1;
            var val = user["ID"];
            Console.WriteLine(val);
            Console.ReadKey();
        }
    }
}

常量

什么是常量

  • 常量constant是表示常量值,即可以在编译时计算的值的类成员。
  • 常量隶属于类型而非对象,即没有实例常量。实例常量的角色由只读实例来担当。
  • 注意区分成员常量与局部常量

常量的声明

using System;

namespace Test
{
    class Web
    {
        public const string URL = "http://www.baidu.com";
    }
    class Program
    {
        static double GetArea(double r)
        {
            return Math.PI * r * r;
        }
        static void Main(string[] args)
        {
            Console.WriteLine(Web.URL);
            Console.ReadKey();
        }
    }
}

各种只读的应用场景

  • 为了提高程序可读性和执行效率 - 常量
  • 为了防止对象的值被改变 - 只读字段
  • 向外暴露不允许修改的数据 - 只读属性(静态或非静态),功能与常量有些重叠。
  • 当希望成为常量的值其类型不能被常量声明接受时(类或自定义结构体) - 静态只读字段
using System;

namespace Test
{
    class Program
    {
        static double GetArea(double r)
        {
            return Math.PI * r * r;
        }
        static void Main(string[] args)
        {
            Console.WriteLine(Int32.MaxValue);
            Console.ReadKey();
        }
    }
}
2010-12-29 17:15:00 plean 阅读数 754
今天想不起C#中类的默认访问修饰符是internal了还以为是public呢,单元测试时候一直是黄色敬告。 所以把csdn的东西翻出了(在百度上搜不到的)。当用internal修饰类(c#默认不加修饰符就是internal)可能会出现问题:当你在继承或 者是实例化一个internal类的时候你的访问权限不能打破原来internal类的访问限制。
例:internal class A{}
        public class B:A{}是不允许的;
        public class C{ public A a=new A();}是不允许的.
 
msdn参考:
访问修饰符(C# 编程指南)

所有类型和类型成员都具有可访问性级别,用来控制是否可以在您程序集的其他代码中或其他程序集中使用它们。您在声明类型或成员时使用以下访问修饰符之一来指定其可访问性:

public (可以修饰类)

同一程序集中的任何其他代码或引用该程序集的其他程序集都可以访问该类型或成员。

private (成员的默认访问修饰符)

只有同一类或结构中的代码可以访问该类型或成员。

protected

只有同一类或结构或者派生类中的代码可以访问该类型或成员。

internal (可以修饰类,类的默认修饰符)

同一程序集中的任何代码都可以访问该类型或成员,但其他程序集中的代码不可以。

protected internal

同一程序集中的任何代码或其他程序集中的任何派生类都可以访问该类型或成员。

下面的示例演示如何为类型和成员指定访问修饰符:

不是所有访问修饰符都可以在所有上下文中由所有类型或成员使用,在某些情况下类型成员的可访问性受到其包含类型的可访问性的限制。以下各节提供了有关可访问性的更多详细信息。

直接在命名空间中声明的类和结构(即,没有嵌套在其他类或结构中的类和结构)可以是公共类和结构,也可以是内部类和结构。如果不指定访问修饰符,则默认为 internal 。嵌套的类和结构还可以声明为私有类和结构。不可以从包含类型访问私有嵌套类型。

派生类的可访问性不能高于其基类型 。换句话说,不能有从内部类 A 派生的公共类 B 。如果允许这种情况,将会使 A 成为公共类,因为 A 的所有受保护的成员或内部成员都可以从派生类访问。

可以使用 InternalsVisibleToAttribute 使其他某些程序集能够访问您的内部类型。有关更多信息,请参见友元程序集(C# 编程指南)

可以使用五种访问类型中的任何一种来声明类成员(包括嵌套的类和结构)。结构成员无法声明为受保护成员,因为结构不支持继承。

成员的可访问性决不能高于其包含类型的可访问性。例如,在内部类型中声明的公共方法只具有内部可访问性。

如果类或结构的成员为属性、字段、方法、事件或委托,并且该成员是某个类型或具有参数或返回值类型,则该成员的可访问性不能超过该类型。例如,如果 C 不是公共类,则不能返回类 C 的公共方法 M 。同样,如果 A 声明为私有,则类型 A 不能有受保护的属性。

用户定义的运算符必须始终声明为公共运算符。有关更多信息,请参见 operator(C# 参考)

析构函数不能具有可访问性修饰符。

若要设置类成员或结构成员的访问级别,请向该成员声明添加适当的关键字。下面是一些示例:

说明:

protected internal 可访问性的意思是受保护“或”内部,而不是受保护“和”内部。换句话说,可以从同一程序集内的任何类(包括派生类)中访问 protected internal 成员。若要限制为只有同一程序集内的派生类可以访问,请将类本身声明为内部,并将其成员声明为受保护。

直接用命名空间声明时,可以将接口声明为公共接口或内部接口,并且与类和结构一样,接口默认具有内部可访问性。接口成员始终是公共成员,因为接口的用途是让其他类型能够访问某个类或结构。访问修饰符不能应用于接口成员。

枚举成员始终是公共的,不能应用任何访问修饰符。

默认情况下,委托默认具有内部访问级别。

2008-09-05 00:36:00 jjjjj102310253 阅读数 1306
今天想不起C#中类的默认访问修饰符是internal了还以为是public呢,单元测试时候一直是黄色敬告。所以把csdn的东西翻出了(在百度上搜不到的)。当用internal修饰类(c#默认不加修饰符就是internal)可能会出现问题:当你在继承或者是实例化一个internal类的时候你的访问权限不能打破原来internal类的访问限制。
例:internal class A{}
        public class B:A{}是不允许的;
        public class C{ public A a=new A();}是不允许的.
 
msdn参考:
访问修饰符(C# 编程指南)

所有类型和类型成员都具有可访问性级别,用来控制是否可以在您程序集的其他代码中或其他程序集中使用它们。您在声明类型或成员时使用以下访问修饰符之一来指定其可访问性:

public (可以修饰类)

同一程序集中的任何其他代码或引用该程序集的其他程序集都可以访问该类型或成员。

private (成员的默认访问修饰符)

只有同一类或结构中的代码可以访问该类型或成员。

protected

只有同一类或结构或者派生类中的代码可以访问该类型或成员。

internal (可以修饰类,类的默认修饰符)

同一程序集中的任何代码都可以访问该类型或成员,但其他程序集中的代码不可以。

protected internal

同一程序集中的任何代码或其他程序集中的任何派生类都可以访问该类型或成员。

下面的示例演示如何为类型和成员指定访问修饰符:

不是所有访问修饰符都可以在所有上下文中由所有类型或成员使用,在某些情况下类型成员的可访问性受到其包含类型的可访问性的限制。以下各节提供了有关可访问性的更多详细信息。

直接在命名空间中声明的类和结构(即,没有嵌套在其他类或结构中的类和结构)可以是公共类和结构,也可以是内部类和结构。如果不指定访问修饰符,则默认为 internal。嵌套的类和结构还可以声明为私有类和结构。不可以从包含类型访问私有嵌套类型。

派生类的可访问性不能高于其基类型。换句话说,不能有从内部类 A 派生的公共类 B。如果允许这种情况,将会使 A 成为公共类,因为 A 的所有受保护的成员或内部成员都可以从派生类访问。

可以使用 InternalsVisibleToAttribute 使其他某些程序集能够访问您的内部类型。有关更多信息,请参见友元程序集(C# 编程指南)

可以使用五种访问类型中的任何一种来声明类成员(包括嵌套的类和结构)。结构成员无法声明为受保护成员,因为结构不支持继承。

成员的可访问性决不能高于其包含类型的可访问性。例如,在内部类型中声明的公共方法只具有内部可访问性。

如果类或结构的成员为属性、字段、方法、事件或委托,并且该成员是某个类型或具有参数或返回值类型,则该成员的可访问性不能超过该类型。例如,如果 C 不是公共类,则不能返回类 C 的公共方法 M。同样,如果 A 声明为私有,则类型 A 不能有受保护的属性。

用户定义的运算符必须始终声明为公共运算符。有关更多信息,请参见 operator(C# 参考)

析构函数不能具有可访问性修饰符。

若要设置类成员或结构成员的访问级别,请向该成员声明添加适当的关键字。下面是一些示例:

说明:

protected internal 可访问性的意思是受保护“或”内部,而不是受保护“和”内部。换句话说,可以从同一程序集内的任何类(包括派生类)中访问 protectedinternal 成员。若要限制为只有同一程序集内的派生类可以访问,请将类本身声明为内部,并将其成员声明为受保护。

直接用命名空间声明时,可以将接口声明为公共接口或内部接口,并且与类和结构一样,接口默认具有内部可访问性。接口成员始终是公共成员,因为接口的用途是让其他类型能够访问某个类或结构。访问修饰符不能应用于接口成员。

枚举成员始终是公共的,不能应用任何访问修饰符。

默认情况下,委托默认具有内部访问级别。

C#类成员-事件

阅读数 2682

C#类成员-析构函数

阅读数 2049

C#类成员-构造函数

阅读数 6877

C#类成员—字段

阅读数 582

没有更多推荐了,返回首页