没有命名空间的类的 C# 公共成员可见性

C# public members visibility of a class with no namespace

提问人:UserControl 提问时间:3/26/2022 最后编辑:UserControl 更新时间:4/5/2022 访问量:568

问:

我有一个项目,我将其作为 MyNuget 包发布到本地源中。该项目引用了一个 ThirdPartyNuget,该 ThirdPartyNuget 具有公共静态类,其中有公共扩展方法。ThirdPartyExtensionsIQueryable

现在,在我的主要解决方案中,我引用了 MyNuget,并且不引用 ThirdPartyNuget。不过,Visual Studio 2022 显示了 中的扩展方法。为什么?ThirdPartyExtensions

我不希望出现这种情况,因为我认为 ThirdPartyNuget 是 MyNuget 的实现细节。

ThirdPartyNuget 中的程序集经过混淆处理,类看起来很奇怪,因为它没有命名空间。以下是我在调试器中看到的内容:ThirdPartyExtensions

typeof(ThirdPartyExtensions).Name == typeof(ThirdPartyExtensions).FullName == "ThirdPartyExtensions"
typeof(ThirdPartyExtensions).Namespace == null
typeof(ThirdPartyExtensions).GUID == {00000000-0000-0000-0000-000000000000}

这种行为的机制是什么?

如何在主解决方案中隐藏可见性?ThirdPartyExtensions

C# .NET 命名空间 依赖项 可见性

评论

0赞 yueyinqiu 3/26/2022
我认为这应该归咎于第三方包,他们在没有命名空间中定义了该类。而且你无法修复它。

答:

2赞 Dilshod K 3/30/2022 #1

如果未为类声明命名空间,则使用默认的全局命名空间。全局命名空间是包含未在命名命名空间中声明的命名空间和类型的命名空间。请看这里

您可以使用关键字查看没有命名空间的类。仅当关键字是限定符的左侧标识符时,该关键字才是全局命名空间别名。欲了解更多信息,请阅读此处globalglobal::

In my main solution I reference MyNuget and DO NOT reference ThirdPartyNuget.但是你引用了.这意味着,您的项目也将被引用。MyNugetThirdPartyNugetThirdPartyNuget

无法隐藏扩展的可见性,但是......

你的期望和目标看起来很奇怪。Hovewer,你可以做这样的事情:

如果你的目标是:不允许在你的项目中使用该扩展方法,你可以创建具有空命名空间的相同扩展类。例如,项目具有以下扩展名(无命名空间):MyNugetThirdPartyNuget

public static class ThirdPartyExtensions
{
    public static void DoSome(this string value)
    {
        //Do some
    }
}

只需在 中创建相同的类并尝试在您的项目中使用它。您将从编译器:)中得到模棱两可的错误。MyNuget

因此,它不会隐藏它,但不允许使用此扩展

评论

0赞 UserControl 3/31/2022
嗯,有意思。但是,如果开发人员通过引入别名来修复命名空间冲突,他仍然能够从中调用函数,不是吗?ThirdPartyNuget
0赞 Dilshod K 4/1/2022
@UserControl 他不能。它们都位于全局命名空间下。
7赞 Kote 3/31/2022 #2

如果你对你的包依赖项使用格式,那么 你的标签就可以了。
https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#controlling-dependency-assets
PackageReferencePrivateAssetMyNuget.csproj

您可能纯粹将依赖项用作开发工具,并且可能不希望将其公开给将使用包的项目。在此方案中,可以使用 PrivateAssets 元数据来控制此行为。

<PackageReference Include="ThirdPartyNuget" Version="1.0.0">
    <PrivateAssets>compile</PrivateAssets>
</PackageReference>

或者,可以按照以下问题
中所述使用 :创建 NuGet 包时,不要包含 packages.config 文件中的依赖项
developmentDependencypackages.config


至于“为什么公共依赖是默认方式?”的问题,我会说:它让生活更轻松。

使用具有公共依赖项的包更容易。如果这是默认行为,则更容易将它们公开。
例如,许多用于 Web 开发的软件包都依赖于 .要配置序列化,需要公开它。关于这一点的另一种看法。
可能 MS 的人对此有一些统计数据。但我没有看到任何关于这方面的文章。他们只推荐它作为默认方式。
Newtonsoft.json


就您的情况而言,我不确定我是否正确复制了它。

在我的测试中,我创建了三个项目:
一个默认命名空间为空的子包。enter image description here一个包,引用具有 PrivateAssets 属性的 SubPackage。enter image description here enter image description here和 project,它引用 Package,但不引用 SubPackage。enter image description here如果我尝试使用扩展,它不会编译。 但是如果我使用方法,则在运行时打印“2”。
GetNumber

如果我正确理解了问题,那就是想要的结果。
但我不确定,它是否适用于您的修补包。
ThirdPartyNuget

评论

1赞 UserControl 3/31/2022
谢谢你,Kote!设置标志从主包的 bin 输出文件夹中删除。所以我可以编译它但不能使用它,在运行时得到“System.IO.FileNotFoundException:无法加载文件或程序集”。PrivateAssetsNugetSubPack.dll
1赞 Kote 4/1/2022
@UserControl,谢谢。是的,前面的例子是错误的,它没有复制.正确的方法是仅将资产标记为私有资产。.NugetSubPack.dllcompile<PrivateAssets>compile</PrivateAssets>