【发布时间】:2010-10-11 12:26:20
【问题描述】:
我在大学期间一直在使用public,想知道public、private 和protected 之间的区别?
除了一无所有,static 还能做什么?
【问题讨论】:
标签: c# .net asp.net access-modifiers
我在大学期间一直在使用public,想知道public、private 和protected 之间的区别?
除了一无所有,static 还能做什么?
【问题讨论】:
标签: c# .net asp.net access-modifiers
同一程序集或引用它的其他程序集中的任何其他代码都可以访问该类型或成员。
类型或成员只能被同一类或结构中的代码访问。
类型或成员只能由同一类或结构中的代码或派生类中的代码访问。
private protected(在 C# 7.2 中添加)类型或成员只能由同一类或结构中的代码访问,或者同一程序集的派生类中的代码访问,但不能从另一个程序集访问。
同一程序集中的任何代码都可以访问类型或成员,但不能从另一个程序集中访问。
同一程序集中的任何代码或另一个程序集中的任何派生类都可以访问该类型或成员。
当没有设置访问修饰符时,使用默认的访问修饰符。所以总会有某种形式的访问修饰符,即使它没有设置。
static modifier类上的 static 修饰符意味着该类不能被实例化,并且它的所有成员都是静态的。静态成员有一个版本,无论创建了多少其封闭类型的实例。
静态类与非静态类基本相同,但有一个区别:静态类不能被外部实例化。换句话说,您不能使用 new 关键字来创建类类型的变量。因为没有实例变量,所以您可以使用类名本身来访问静态类的成员。
但是,有一个 static constructor 这样的东西。任何类都可以有其中之一,包括静态类。它们不能直接调用并且不能有参数(除了类本身的任何类型参数)。在创建第一个实例或引用任何静态成员之前,会自动调用静态构造函数来初始化类。看起来像这样:
static class Foo()
{
static Foo()
{
Bar = "fubar";
}
public static string Bar { get; set; }
}
静态类通常用作服务,您可以这样使用它们:
MyStaticClass.ServiceMethod(...);
【讨论】:
图形概述(简而言之)
由于static classes 是密封的,它们不能被继承(从Object 除外),因此关键字protected 在静态类上无效。
如果您没有在前面放置访问修饰符,则默认设置请参见此处:
Default visibility for C# classes and members (fields, methods, etc.)?
非嵌套
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-keyword,它使类不可继承。
另外,在 VB.NET 中,关键字有时是不同的,所以这里有一个备忘单:
【讨论】:
Public - 如果你能看到类,那么你就能看到方法
Private - 如果您是该类的一部分,那么您可以看到该方法,否则不能。
Protected - 与 Private 相同,加上所有 后代 也可以看到该方法。
静态(类) - 还记得“类”和“对象”之间的区别吗?忘记这一切。它们与“静态”相同......该类是其自身的唯一实例。
静态(方法) - 每当您使用此方法时,它都会有一个独立于它所属的类的实际实例的参考框架。
【讨论】:
转发来自this answer 的精彩图表。
这里是维恩图中的所有访问修饰符,从更多限制到更混杂:
private:
private protected: - added in C# 7.2
internal:
protected:
protected internal:
public:
【讨论】:
当前access modifier (C# 7.2) 的另一种可视化方法。希望架构有助于更轻松地记住它
(单击图像以查看交互式视图。)
如果您难以记住两个词的访问修饰符,请记住 outside-inside。
【讨论】:
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();
}
}
}
【讨论】:
Private Protected,它将是:相同的 class= Yes,相同的程序集,派生的 class= Yes,相同的程序集,任何 class= NO,不同的程序集,派生 class= NO,不同的程序集,任何 class= NO。还有一个建议是不要切换protected internal 的词序,因为这会破坏@user1810087 的答案
关于Nothing
的问题【讨论】:
嗯。
请看这里:Access Modifiers。
简而言之:
Public 使方法或类型从其他类型/类中完全可见。
Private 只允许包含私有方法/变量的类型访问私有方法/变量(注意嵌套类也可以访问包含类的私有方法/变量)。
Protected 类似于 private,只是派生类也可以访问受保护的方法。
“Nothing”在 VB.NET 中等同于 null。尽管如果您指的是“无”,意思是“没有访问修饰符”,那么这取决于,尽管一个非常粗略的经验法则(当然在 C# 中)是,如果您没有显式指定访问修饰符,则方法/变量声明通常尽可能受限。 即
public class MyClass
{
string s = "";
}
实际上等同于:
public class MyClass
{
private string s = "";
}
链接的 MSDN 文章将在没有明确指定访问修饰符时提供完整描述。
【讨论】:
public - 任何地方的任何人都可以访问。
private - 只能从它所属的类中访问。
protected - 只能从类中的 with 或从该类继承的任何对象中访问。
在 VB 中,没有什么比 null 更重要了。
静态意味着您拥有该对象的一个实例,该类的每个实例的方法。
【讨论】:
嗯……
静态意味着您可以在没有类实例的情况下访问该函数。
您可以直接从类定义中访问。
【讨论】:
Private 状态表示变量只能被同一类的对象访问。受保护状态将访问权限扩展到包括该类的后代。
“从上表中我们可以看到私有和受保护之间的区别......我认为两者都是相同的......所以需要这两个单独的命令”
查看MSDN链接了解更多信息
【讨论】:
这些访问修饰符指定您的成员在哪里可见。您可能应该阅读此内容。以 IainMH 给出的链接为起点。
静态成员每个类一个,而不是每个实例一个。
【讨论】:
小心!观看您的课程的可访问性。默认情况下,所有人都可以访问公共和受保护的类和方法。
此外,在 Visual Studio 中创建新类时,Microsoft 在显示访问修饰符(public、protected 等关键字)方面并不是很明确。因此,请注意并考虑您的类的可访问性,因为它是您实现内部的大门。
【讨论】:
我认为这与良好的 OOP 设计有关。如果你是一个库的开发者,你想隐藏你的库的内部工作。这样,您可以稍后修改您的库内部工作。所以你把你的成员和辅助方法设置为私有的,只有接口方法是公共的。应该被覆盖的方法应该受到保护。
【讨论】:
C# 总共有 6 个访问修饰符:
private:使用此可访问性声明的成员可以在包含类型中可见,它对任何派生类型、同一程序集中的其他类型或包含程序集之外的类型均不可见。即,访问仅限于包含类型。
protected:使用此可访问性声明的成员可以在从包含程序集内的包含类型派生的类型中可见,以及从包含程序集外部的包含类型派生的类型中可见。即,访问仅限于包含类型的派生类型。
internal:使用此可访问性声明的成员可以在包含此成员的程序集中可见,它对包含程序集之外的任何程序集都不可见。即,访问仅限于包含程序集。
internal protected:使用此可访问性声明的成员可以在从包含程序集内部或外部的包含类型派生的类型中可见,它也对包含程序集内的任何类型可见。即,访问仅限于包含程序集或派生类型。
public:使用此可访问性声明的成员可以在包含该成员的程序集中或引用包含该程序集的任何其他程序集中可见。即,访问不受限制。
在 C# 7.2 中,添加了新级别的可访问性:
private protected:使用此可访问性声明的成员可以在从包含程序集中的此包含类型派生的类型中可见。对于不是从包含类型派生的任何类型或在包含程序集之外的任何类型,它都是不可见的。即,访问仅限于包含程序集中的派生类型。
Source including a sample code of the new private protected access modifier
【讨论】:
public 表示它可以被任何程序集中的任何类访问,包括类本身。protected internal 表示它可以被类本身访问(在类定义中),并且可以被当前程序集中的任何类访问,但在程序集之外它只能被继承该类的类访问,或通过类本身(如果它是部分类) - 基本上它意味着程序集内的 internal 和程序集外的 protected。protected 表示它只能由类本身访问,或者由继承它的类访问,并且该类可以在任何程序集中internal 表示它可以由类本身或程序集中的任何类访问,但在程序集之外根本无法访问,除非由类本身(即它是一个部分类)private protected 表示它只能由类本身访问,或者它可以由继承它的类访问,并且只有当该类在当前程序集中时才能访问。在程序集之外,它只能由类本身访问(即它是一个部分类)——基本上结合了internal和protected,或者另一种说法是它在程序集之外是private和@ 987654332@ 在程序集中。private 表示只能由类本身访问private,对于非嵌套类是internal。在上面的文本中,“访问”意味着通过类类型的对象进行访问,在类本身的方法中,该对象将是隐式的 this 对象,或者该方法实例化了当前类类型的显式对象并通过该对象访问它。两者都被认为是由类本身访问的,因此访问规则是相同的。这也适用于从静态方法执行的访问,或者当它是被访问的静态成员/方法时,除了使用类范围而不是对象执行访问。静态类的成员/方法需要显式设置为static,否则无法编译。
非嵌套类可以是public 或internal,默认为internal。嵌套的类可以是任何访问类型,如果父类是静态的,它不需要是静态的,它的成员也不需要。 internal 类意味着它只能被实例化,或者它的静态成员只能从当前程序集中访问。
您可以在internal 或private 嵌套类中拥有公共成员/方法/嵌套类——只有低于级别的访问说明符(在正在进行的访问的完全限定名称中)正在进行的当前访问中的 required 会阻止访问。
C#中的继承总是public,不像C++,它可以私有或受保护地继承,然后改变所有类的访问权限,然后继承自该类的类,以及通过对象/通过从类中私有/受保护地继承的类的类型的类范围以及从私有/受保护地继承的类继承的类形成该类,依此类推。访问权限已更改,所有限制性低于private 或protected 的访问修饰符分别设为private 和protected。
【讨论】: