大学期间我一直在使用public,想知道public, private和protected之间的区别吗?
还有,相对于什么都没有,静态有什么作用呢?
大学期间我一直在使用public,想知道public, private和protected之间的区别吗?
还有,相对于什么都没有,静态有什么作用呢?
Hmm.
参见这里:访问修饰符。
简而言之:
Public使方法或类型从其他类型/类中完全可见。
Private只允许包含私有方法/变量的类型访问私有方法/变量(注意,嵌套类也可以访问包含类的私有方法/变量)。
Protected与private类似,只是派生类也可以访问Protected方法。
“Nothing”是VB。NET等价于null。虽然如果你提到的“nothing”意味着“没有访问修饰符”,那么这要视情况而定,尽管一个非常粗略的经验法则(当然在c#中)是,如果你没有显式地指定访问修饰符,方法/变量声明通常会受到尽可能多的限制。 即。
public class MyClass
{
string s = "";
}
实际上等同于:
public class MyClass
{
private string s = "";
}
当没有显式指定访问修饰符时,链接的MSDN文章将提供完整的描述。
访问修饰符
从learn.microsoft.com:
public The type or member can be accessed by any other code in the same assembly or another assembly that references it. private The type or member can only be accessed by code in the same class or struct. protected The type or member can only be accessed by code in the same class or struct, or in a derived class. private protected (added in C# 7.2) The type or member can only be accessed by code in the same class or struct, or in a derived class from the same assembly, but not from another assembly. internal The type or member can be accessed by any code in the same assembly, but not from another assembly. protected internal The type or member can be accessed by any code in the same assembly, or by any derived class in another assembly.
如果没有设置访问修饰符,则使用默认访问修饰符。所以总有某种形式的访问修饰符,即使它没有设置。
静态修饰符
类上的静态修饰符意味着该类不能被实例化,并且它的所有成员都是静态的。静态成员只有一个版本,不管创建了多少个其封闭类型的实例。
静态类基本上与非静态类相同,但有一个区别:静态类不能被外部实例化。换句话说,不能使用new关键字创建类类型的变量。因为没有实例变量,所以可以使用类名本身访问静态类的成员。
然而,存在一种静态构造函数。任何类都可以有其中一个,包括静态类。它们不能被直接调用,也不能有参数(除了类本身的任何类型参数)。在创建第一个实例或引用任何静态成员之前,会自动调用静态构造函数来初始化类。看起来是这样的:
static class Foo()
{
static Foo()
{
Bar = "fubar";
}
public static string Bar { get; set; }
}
静态类通常被用作服务,你可以这样使用它们:
MyStaticClass.ServiceMethod(...);
公共-任何人在任何地方都可以访问。 Private -只能从它所属的类中的with访问。 Protected -只能从类中的with或从类继承的任何对象访问。
除了在VB中,没有什么是像null的。 静态意味着你有那个对象的一个实例,那个类的每个实例都有方法。
我认为这与好的面向对象设计有关。如果您是库的开发人员,则希望隐藏库的内部工作方式。这样,以后就可以修改库的内部工作方式。所以你把你的成员和辅助方法设为私有,只有接口方法是公共的。应该被覆盖的方法应该受到保护。
小心!注意类的可访问性。默认情况下,所有人都可以访问公共和受保护的类和方法。
此外,微软在显示访问修饰符(公共的,受保护的,等等。关键字)当Visual Studio中创建新类时。因此,请仔细考虑类的可访问性,因为它是通往实现内部的大门。
Public -如果你能看到类,那么你也能看到方法
Private -如果你是类的一部分,那么你可以看到这个方法,否则就不能。
Protected -与Private相同,加上所有后代也可以看到该方法。
静态(类)——还记得“类”和“对象”之间的区别吗?忘掉这些吧。“static”也是如此。类是自身的唯一实例。
静态(方法)——无论何时使用这个方法,它都有一个独立于它所属类的实际实例的参考框架。
Private状态表示变量只能被同一类的对象访问。受保护状态将这种访问权限扩展到该类的后代。
“从上表中我们可以看到隐私和受保护之间的区别……我认为两者是一样的....那么这两个单独的命令有什么用呢?
查看MSDN链接了解更多信息
图形概述(简要总结)
实际上,情况要比这复杂一些。 现在(从c# 7.2开始),也有private protected,派生类是否在同一个程序集中也很重要。
因此,需要扩展概述:
请参阅有关此主题的c# -dotnet-docs。
因为静态类是密封的,所以它们不能被继承(除非是从Object继承),所以关键字protected在静态类上是无效的。
对于默认情况,如果你在前面不放访问修饰符,请参见这里: c#类和成员(字段,方法等)的默认可见性?
Non-nested
enum public
non-nested classes / structs internal
interfaces internal
delegates in namespace internal
class/struct member(s) private
delegates nested in class/struct private
嵌套:
nested enum public
nested interface public
nested class private
nested struct private
此外,还有seal -关键字,它使类不可继承。 同样,在VB中。NET,关键字有时是不同的,所以这里有一个小抄:
using System;
namespace ClassLibrary1
{
public class SameAssemblyBaseClass
{
public string publicVariable = "public";
protected string protectedVariable = "protected";
protected internal string protected_InternalVariable = "protected internal";
internal string internalVariable = "internal";
private string privateVariable = "private";
public void test()
{
// OK
Console.WriteLine(privateVariable);
// OK
Console.WriteLine(publicVariable);
// OK
Console.WriteLine(protectedVariable);
// OK
Console.WriteLine(internalVariable);
// OK
Console.WriteLine(protected_InternalVariable);
}
}
public class SameAssemblyDerivedClass : SameAssemblyBaseClass
{
public void test()
{
SameAssemblyDerivedClass p = new SameAssemblyDerivedClass();
// NOT OK
// Console.WriteLine(privateVariable);
// OK
Console.WriteLine(p.publicVariable);
// OK
Console.WriteLine(p.protectedVariable);
// OK
Console.WriteLine(p.internalVariable);
// OK
Console.WriteLine(p.protected_InternalVariable);
}
}
public class SameAssemblyDifferentClass
{
public SameAssemblyDifferentClass()
{
SameAssemblyBaseClass p = new SameAssemblyBaseClass();
// OK
Console.WriteLine(p.publicVariable);
// OK
Console.WriteLine(p.internalVariable);
// NOT OK
// Console.WriteLine(privateVariable);
// Error : 'ClassLibrary1.SameAssemblyBaseClass.protectedVariable' is inaccessible due to its protection level
//Console.WriteLine(p.protectedVariable);
// OK
Console.WriteLine(p.protected_InternalVariable);
}
}
}
using System;
using ClassLibrary1;
namespace ConsoleApplication4
{
class DifferentAssemblyClass
{
public DifferentAssemblyClass()
{
SameAssemblyBaseClass p = new SameAssemblyBaseClass();
// NOT OK
// Console.WriteLine(p.privateVariable);
// NOT OK
// Console.WriteLine(p.internalVariable);
// OK
Console.WriteLine(p.publicVariable);
// Error : 'ClassLibrary1.SameAssemblyBaseClass.protectedVariable' is inaccessible due to its protection level
// Console.WriteLine(p.protectedVariable);
// Error : 'ClassLibrary1.SameAssemblyBaseClass.protected_InternalVariable' is inaccessible due to its protection level
// Console.WriteLine(p.protected_InternalVariable);
}
}
class DifferentAssemblyDerivedClass : SameAssemblyBaseClass
{
static void Main(string[] args)
{
DifferentAssemblyDerivedClass p = new DifferentAssemblyDerivedClass();
// NOT OK
// Console.WriteLine(p.privateVariable);
// NOT OK
//Console.WriteLine(p.internalVariable);
// OK
Console.WriteLine(p.publicVariable);
// OK
Console.WriteLine(p.protectedVariable);
// OK
Console.WriteLine(p.protected_InternalVariable);
SameAssemblyDerivedClass dd = new SameAssemblyDerivedClass();
dd.test();
}
}
}
c#总共有6个访问修饰符:
private:使用此可访问性声明的成员可以在包含类型中可见,但对任何派生类型、同一程序集中的其他类型或包含程序集中之外的类型都不可见。也就是说,访问仅限于包含类型。
protected:使用此可访问性声明的成员可以在包含程序集中从包含类型派生的类型中可见,也可以在包含程序集中从包含类型派生的类型中可见。也就是说,只能访问包含类型的派生类型。
internal:使用此可访问性声明的成员可以在包含该成员的程序集内可见,它对包含该成员的程序集之外的任何程序集都不可见。也就是说,访问仅限于包含程序集。
internal protected:使用此可访问性声明的成员可以在包含程序集内部或外部从包含类型派生的类型中可见,它也对包含程序集内的任何类型可见。也就是说,访问仅限于包含程序集或派生类型。
public:使用此可访问性声明的成员可以在包含此成员的程序集或引用包含该成员的程序集的任何其他程序集中可见。也就是说,访问不受限制。
在c# 7.2中,增加了一个新的可访问性级别:
private protected:使用此可访问性声明的成员可以在包含程序集中从此包含类型派生的类型中可见。对于非从包含类型派生的任何类型或包含程序集外部的任何类型都不可见。也就是说,访问权限仅限于包含程序集中的派生类型。
源代码,包括新的私有受保护访问修饰符的示例代码
重新发布这个答案的精彩图表。
以下是维恩图中的所有访问修饰语,从更有限制的到更混杂的: 私人: private protected: c# 7.2新增 内部: 保护: 保护内部: 公众:
当前访问修饰符的另一种可视化方法(c# 7.2)。希望这个模式能帮助你更容易地记住它 (请按此图片浏览。)
外内
如果你很难记住两个词的访问修饰符,记住由外而内。
Private protected:外部私有(相同程序集)内部受保护(相同程序集) 保内:保外(同一组件)保内(同一组件)
public means that it can be accessed by any class in any assembly, which includes the class itself. protected internal means it can be accessed by the class itself (in the class definition), and it can be accessed by any class in the current assembly, but outside of the assembly it can only be accessed by a class that inherits the class, or by the class itself (if it is a partial class) – basically it means internal inside the assembly and protected outside of the assembly. protected means it can only be accessed by the class itself, or accessed by a class that inherits it and that class can be in any assembly internal means it can be accessed by the class itself or by any class in the assembly but can't be accessed at all outside of the assembly unless by the class itself (i.e. it is a partial class) private protected means it can only be accessed by the class itself, or it can be accessed by a class that inherits it and only if that class is in the current assembly. Outside of the assembly, it can only be accessed by the class itself (i.e. it is a partial class) – basically combines internal and protected, or another way of putting it is it's private outside of the assembly and protected inside the assembly. private means that it can only be accessed by the class itself no access modifier: The default access for everything in C# is "the most restricted access you could declare for that member"., which is private for a member / method / nested class in a class and internal for a non-nested class.
In the above text 'accessed' means accessed via an object of the class type, which within a method of the class itself will be the implicit this object, or perhaps the method instantiates an explicit object of the current class type and accesses it through that object. Both are considered to be being accessed by the class itself and therefore the access rules are the same. This also applies to an access being performed from a static method, or when it is a static member / method being accessed, except the access is performed using the class scope and not and object. A member / method of a static class needs to be explicitly made static or it won't compile.
没有嵌套的类可以是公共的,也可以是内部的,默认情况下是内部的。嵌套的类可以是任何访问类型,如果父类是静态的,它就不需要是静态的,它的成员也不需要是静态的。内部类意味着只能实例化它或从当前程序集访问它的静态成员。
您可以在内部或私有嵌套类中拥有公共成员/方法/嵌套类——只有访问说明符(在正在进行的访问的完全限定名称中)低于当前正在进行的访问所需的级别才能阻止访问。
Inheritance in C# is always public unlike C++, which can privately or protectedly inherit, which then changes the access of all classes that then inherit from the class that is inheriting from this class, as well as the access via object / via class scope of type of the class that inheriting privately / protectedly from the class and the class that is inheriting from the class that is inheriting privately / protectedly form the class, and so on. The access is changed such that all access modifiers less restrictive than private or protected are made private and protected respectively.
我创建了另一种类型的可视化。也许这是更好的理解方式
https://github.com/TropinAlexey/C-sharp-Access-Modifiers
类型或成员可以被同一程序集中的任何其他代码或引用它的另一个程序集中的任何其他代码访问。类型的公共成员的可访问性级别由类型本身的可访问性级别控制。
该类型或成员只能被相同类或结构中的代码访问。
内部类型或成员只能在同一程序集中的文件中访问。
protected类型或成员只能被同一类中的代码或从该类派生的类中的代码访问。 internal:类型或成员可以被同一程序集中的任何代码访问,但不能从另一个程序集中访问。换句话说,内部类型或成员可以从属于同一编译的代码中访问。 protected internal:类型或成员可以由声明它的程序集中的任何代码访问,也可以从另一个程序集中的派生类中访问。
类型或成员可以由在其包含程序集中声明的类派生的类型访问。
受保护的内部成员可从当前程序集或从包含类派生的类型访问。
静态修饰符用于声明静态成员,该成员属于类型本身,而不属于特定对象。静态修饰符可用于声明静态类。在类、接口和结构中,可以向字段、方法、属性、操作符、事件和构造函数添加静态修饰符。
在c# 11中,您还可以使用文件访问修饰符。
文件修饰符将顶级类型的作用域和可见性限制在声明顶级类型的文件中。文件修饰符通常应用于源生成器编写的类型。文件-本地类型为源生成器提供了一种方便的方法来避免所生成类型之间的名称冲突。
// In File1.cs:
file interface IWidget
{
int ProvideAnswer();
}
file class HiddenWidget
{
public int Work() => 42;
}
public class Widget : IWidget
{
public int ProvideAnswer()
{
var worker = new HiddenWidget();
return worker.Work();
}
}