C# 试题 08:访问级别与程序集
0141 以下代码(同一程序集内)能否编译?若编译,输出什么?
难度: 实战
internal class Helper
{
public static int N => 1;
}
Console.WriteLine(Helper.N);
- A. 输出
1,同一程序集内internal可访问 - B. 编译失败,
internal类不能访问 - C. 输出
0 - D. 运行抛异常
查看答案与解析
正确答案A
解析: internal 的作用域是整个程序集,同程序集内的任何类型都能访问该成员。
关键点: internal 的边界是“程序集”,不是类,也不是命名空间。
0142 以下代码(同一程序集、不同命名空间)能否编译?
难度: 实战
namespace A
{
internal class C
{
public static int X = 1;
}
}
namespace B
{
class P
{
public static int Get() => A.C.X;
}
}
Console.WriteLine(B.P.Get());
- A. 编译失败,跨命名空间不能访问
internal - B. 编译失败,
C是 internal - C. 输出
1,internal的作用域是整个程序集,与命名空间无关 - D. 运行抛异常
查看答案与解析
正确答案C
解析: internal 的可见范围由程序集决定,命名空间只是组织名称的方式,不构成访问边界,跨命名空间访问合法。
关键点: “命名空间相同才可见”是常见误解,真正边界是程序集。
0143 以下代码(程序集 A 声明基类,程序集 B 中派生)能否编译?
难度: 进阶
// 程序集 A
public class Base
{
protected internal void M() { }
}
// 程序集 B:派生类
class Derived : Base
{
public void Test() => M();
}
- A. 编译失败,
protected internal只能在声明程序集内访问 - B. 编译失败,跨程序集派生类不能访问基类成员
- C. 编译通过,
protected internal的含义是 protected OR internal,跨程序集派生类经 protected 路径可访问 - D. 编译通过,因为两个类型位于同名命名空间
查看答案与解析
正确答案C
解析: protected internal 是“protected 或 internal”的并集:同程序集任意类型可访问,跨程序集则由 protected 部分授权给派生类,因此 Derived 中调用合法。
关键点: protected internal 的“或”语义允许跨程序集继承访问。
0144 以下代码(程序集 A 声明基类,程序集 B 中派生)能否编译?
难度: 进阶
// 程序集 A
public class Base
{
private protected void M() { }
}
// 程序集 B:派生类
class Derived : Base
{
public void Test() => M();
}
- A. 编译通过,派生类总能访问基类成员
- B. 编译失败,
private protected是 protected AND internal,跨程序集的派生类不满足 internal 部分 - C. 编译通过,
private protected与protected等价 - D. 编译失败,但错误原因是
M()未标记 virtual
查看答案与解析
正确答案B
解析: private protected 是“protected 且 internal”的交集:只有同一程序集内的派生类可访问。跨程序集的派生类不满足 internal,编译失败。
关键点: private protected 比 protected internal 更严格,二者方向相反。
0145 以下代码(同一程序集内)能否编译?
难度: 进阶
public class Base
{
private protected void M() { }
}
class Derived : Base
{
public void Test() => M();
}
- A. 编译通过,同程序集内的派生类同时满足 protected 与 internal
- B. 编译失败
- C. 编译通过,但仅限
Base自身 - D. 运行抛异常
查看答案与解析
正确答案A
解析: 同一程序集内的派生类既满足 protected(是派生类)又满足 internal(同程序集),符合 private protected 的“与”语义。
关键点: private protected 的可见对象是“同程序集的派生类”。
0146 以下代码(程序集 A 声明基类,程序集 B 中的非派生类)能否编译?
难度: 进阶
// 程序集 A
public class Base
{
protected internal void M() { }
}
// 程序集 B:非派生类
class Other
{
public void Test(Base b) => b.M();
}
- A. 编译通过,
internal路径跨程序集仍有效 - B. 编译通过,因为
M()是 public - C. 运行抛异常
- D. 编译失败,跨程序集时只有 protected 部分生效,非派生类无权访问
查看答案与解析
正确答案D
解析: 跨程序集时 protected internal 中的 internal 部分失效,只剩 protected;非派生类既无 internal 权限也不满足 protected,访问编译失败。
关键点: 并集语义在跨程序集场景下退化为“仅 protected”。
0147 以下代码能否编译?
难度: 实战
private class C { }
- A. 编译通过,顶级类默认 private
- B. 编译通过,但其他类型无法看到
- C. 编译失败,顶级类型只能是 public 或 internal(CS1527)
- D. 运行抛异常
查看答案与解析
正确答案C
解析: 顶级类型(命名空间下的类型)只允许 public 或 internal,private、protected 等修饰符只对嵌套类型合法,报 CS1527。
关键点: 访问修饰符的适用范围取决于类型是顶级还是嵌套。
0148 以下代码(程序集 A 声明类型,程序集 B 引用)能否编译?
难度: 实战
// 程序集 A
class C
{
public static int X = 1;
}
// 程序集 B
Console.WriteLine(C.X);
- A. 编译通过,输出
1 - B. 编译通过,输出
0 - C. 编译失败,因为
X不是 public - D. 编译失败,顶级类型无修饰符时默认
internal,跨程序集不可访问
查看答案与解析
正确答案D
解析: 顶级类型省略修饰符时默认 internal,即使成员是 public,跨程序集也因类型不可见而无法访问。
关键点: 成员的可见性不能超过其包含类型,“成员 public”不等于“类型对外可见”。
0149 以下代码能否编译?
难度: 进阶
class C
{
protected internal void A() { }
internal protected void B() { }
private protected void C() { }
}
- A. 编译失败,
internal protected顺序非法 - B. 编译通过,修饰符顺序不影响含义,
protected internal与internal protected相同,private protected为 protected AND internal - C. 编译失败,一个成员不能有多个访问修饰符
- D. 编译通过,但
private protected非法被忽略
查看答案与解析
正确答案B
解析: C# 的修饰符顺序是自由的,protected internal 与 internal protected 完全等价;private protected 也是合法组合(protected AND internal)。
关键点: 看到 internal protected 不要误判为错误,它与 protected internal 同义。
0150 以下代码(程序集 A 与友元程序集 MyTests)能否编译?
难度: 实战
// 程序集 A:AssemblyInfo.cs
[assembly: InternalsVisibleTo("MyTests")]
// 程序集 A
internal class Secret
{
public static int X = 1;
}
// 程序集 MyTests
Console.WriteLine(Secret.X);
- A. 编译通过,输出
1,友元程序集获得 internal 访问权 - B. 编译失败,
internal永远不能跨程序集 - C. 编译通过,但输出
0 - D. 编译失败,属性只能用于测试
查看答案与解析
正确答案A
解析: InternalsVisibleTo 按程序集标识把 internal 成员开放给指定友元程序集,MyTests 中可直接访问 Secret.X。
关键点: 友元程序集机制是 internal 的唯一官方“越界”通道。
0151 程序集 A 与友元程序集 Friend 都是强名称,以下写法能否让 Friend 访问 internal 成员?
难度: 进阶
// 程序集 A
[assembly: InternalsVisibleTo("Friend")]
- A. 能,程序集名匹配即可
- B. 能,但运行时被忽略
- C. 不能,强名称的友元程序集必须在属性中提供匹配的 PublicKey
- D. 不能,强名称程序集无法使用
InternalsVisibleTo
查看答案与解析
正确答案C
解析: 强名称程序集的身份包含名称与公钥;InternalsVisibleTo 只写程序集名时无法与强名称友元程序集匹配,需写成 "Friend, PublicKey=..." 形式。
关键点: 强名称场景下友元授权必须携带公钥,否则授权不生效。
0152 以下代码能否编译?
难度: 进阶
public interface I
{
internal void Hidden() { }
void Visible();
}
class Impl : I
{
public void Visible() { }
}
- A. 编译失败,接口成员不能是 internal
- B. 编译失败,实现类没有实现
Hidden - C. 编译通过,但
Hidden必须 public - D. 编译通过,
Hidden是带默认实现的 internal 接口成员,实现类无需实现
查看答案与解析
正确答案D
解析: 接口默认实现成员(DIM)可以有访问修饰符;internal 的 Hidden 带有实现体,类实现接口时只需实现 public 的 Visible。
关键点: 接口成员默认 public,但默认实现成员可声明更低的可见性。
0153 以下代码能否编译?
难度: 进阶
public class Base
{
protected void M() { }
}
public class Derived : Base
{
public void Test(Base b) => b.M();
}
- A. 编译失败,不能通过基类类型的引用访问 protected 成员(CS1540)
- B. 编译通过
- C. 编译通过,但仅在
b实际是Derived时有效 - D. 运行抛异常
查看答案与解析
正确答案A
解析: protected 成员只能在“当前类或其派生类类型的实例”上访问;b 的静态类型是基类 Base,即使运行时是派生实例也不允许,报 CS1540。
关键点: protected 的访问资格看限定符的静态类型,不是运行时类型。
0154 以下代码能否编译?
难度: 实战
public class Base
{
protected void M() { }
}
public class Derived : Base
{
public void Test(Derived d) => d.M();
}
- A. 编译失败
- B. 编译通过,通过派生类实例访问 protected 成员合法
- C. 运行抛异常
- D. 编译通过,但
M必须 virtual
查看答案与解析
正确答案B
解析: 限定符 d 的类型是 Derived,是当前类本身,访问 protected 成员合法;protected 不要求成员是 virtual。
关键点: protected 与 virtual 是正交概念,前者管可见性,后者管分派。
0155 以下代码输出什么?
难度: 实战
class Outer
{
private static int Secret = 42;
class Inner
{
public static int Read() => Secret;
}
public static int Get() => Inner.Read();
}
Console.WriteLine(Outer.Get());
- A. 编译失败,嵌套类型不能访问外部类型的 private 成员
- B. 输出
0 - C. 运行抛异常
- D. 输出
42,嵌套类型可以访问外部类型(包括 private)成员
查看答案与解析
正确答案D
解析: 嵌套类型是外部类型的成员,可访问外部类型的所有成员(含 private),这是嵌套类型的主要用途之一。
关键点: 嵌套类型对包含类型拥有“全量可见”特权。
0156 以下代码能否编译?
难度: 进阶
class Outer
{
class Inner
{
private static int X = 1;
}
public static int Read() => Inner.X;
}
- A. 编译失败,外部类型不能访问嵌套类型的 private 成员(CS0122)
- B. 编译通过,外部类型可以访问嵌套类型的 private 成员
- C. 输出
1 - D. 运行抛异常
查看答案与解析
正确答案A
解析: 可见性特权是单向的:嵌套类型能访问外部类型的 private,但外部类型不能访问嵌套类型的 private 成员,报 CS0122。
关键点: “嵌套即可见”只对嵌套类型指向外部类型的方向成立。
0157 以下代码能否编译?
难度: 实战
internal class C
{
public void M() { }
}
- A. 编译通过,成员可访问性不能超过其包含类型,实际生效为 internal
- B. 编译失败,public 成员不能放在 internal 类中
- C. 编译通过,且
M在外部程序集仍可通过 public 访问 - D. 运行抛异常
查看答案与解析
正确答案A
解析: 成员的访问域被包含类型收紧:internal 类里的 public 成员实际仍是 internal,编译合法。
关键点: “public 成员放在 internal 类里”不是错误,只是没有 public 效果。
0158 关于 internal 与 InternalsVisibleTo 的契约,哪项正确?
难度: 实战
- A.
internal与public等价 - B.
internal成员对同程序集所有类型可见;InternalsVisibleTo只能授权给一个程序集 - C.
InternalsVisibleTo授权后友元程序集可访问 private 成员 - D.
internal只对同一程序集可见,可用InternalsVisibleTo按程序集标识授权给友元程序集;它不会把 internal API 变成所有调用方都可见,也不会授予 private 访问权
查看答案与解析
正确答案D
解析: InternalsVisibleTo 是白名单机制:只有列出的友元程序集获得 internal 访问权,private 始终不可见,未授权的程序集依旧看不到 internal API。
关键点: 友元授权是“定向开放”,不是“全部公开”。
0159 关于 protected internal 与 private protected 的区别,哪项正确?
难度: 进阶
- A.
protected internal是 protected AND internal;private protected是 protected OR internal - B.
protected internal是 protected OR internal(同程序集任意类型 + 跨程序集派生类);private protected是 protected AND internal(仅同程序集派生类) - C. 两者等价
- D.
private protected比private更严格
查看答案与解析
正确答案B
解析: 并集与交集的差异:protected internal 放行两类访问者,private protected 要求访问者同时满足两个条件,因此可见面更窄。
关键点: 记忆口诀:protected internal 是“或”,private protected 是“且”。
0160 关于顶级类型的可见性,哪项正确?
难度: 实战
- A. 顶级类型可以是任何访问级别
- B. 顶级类型默认 public
- C. 顶级类型只能是 public 或 internal(默认 internal),嵌套类型才能使用 private/protected 等修饰符
- D. 顶级类型不能是 internal
查看答案与解析
正确答案C
解析: 命名空间下的类型只有 public/internal 两种合法级别,省略时默认 internal;private、protected、private protected 仅适用于嵌套类型。
关键点: 判断“修饰符是否合法”先看类型是顶级还是嵌套。