- 桌面应用
- 图像处理
【免费下载链接】greenshot
Greenshot for Windows - for more information look here:
本文以 Greenshot 开源仓库根目录的 CONTRIBUTING.md 为核心骨架,系统解析该项目面向贡献者的 16 条 C# 编码规范与 AI 辅助贡献政策。读者将掌握 Greenshot 代码库的命名、缩进、修饰符、类型使用等具体约束,理解这些规则在真实源码中的落地方式与工具链保障,并熟悉 AI 辅助提交的 CLA 责任边界与透明性要求,可直接用于向该仓库提交高质量 PR 或自查本地代码风格。
一、总则:以 Visual Studio 默认为准
CONTRIBUTING.md 开宗明义:"use Visual Studio defaults"。Greenshot 是一个面向 Windows 的截屏工具,主体代码为 C#,解决方案 src/Greenshot.sln 内含主程序、核心库、编辑器、十余个插件、MCP 服务与测试项目。统一代码风格的意义在于:多项目、多贡献者的场景下,代码评审与 git 历史 diff 只关注逻辑变更而非格式噪音。
二、缩进与括号风格
规范 1:Allman 风格大括号
每个大括号独占一行:
public static void Main(string[] args) { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13; }单行语句块可以省略大括号,但必须满足两个约束:块体在独立行且正确缩进;不得嵌套在其他使用大括号的语句块中。即if (x) return;这种与语句同行的写法不符合规范,应写成:
if (condition) return;规范 2:四空格缩进
统一使用四个空格,禁止 Tab。这一点在 src/Greenshot/GreenshotMain.cs 等源码中处处可见。
规范 8:避免多余空格
禁止"游离空格",例如if (someVar == 0)...中if之后、(之前的多余空格(用...标注的位置)。文档建议使用 Visual Studio 的"View White Space(Ctrl+E, S)"功能辅助排查。
规范 7:空行节制
任何位置最多一个空行,类型成员之间不允许连续两个空行,保持文件紧凑可读。
三、命名规范
规范 3:字段命名_camelCase与三种前缀
- 实例字段前缀
_,如_mutexId、_resourceName; - 静态字段前缀
s_(如s_sharedInstance); - 线程静态字段前缀
t_(如t_localValue); - 内部与私有字段使用
_camelCase,并在可能的情况下声明为readonly; - 静态字段上
readonly必须置于static之后,即static readonly而非readonly static。
源码实证见 src/Greenshot/Helpers/ResourceMutex.cs:
private static readonly ILog Log = LogManager.GetLogger(typeof(ResourceMutex)); private readonly string _mutexId; private readonly string _resourceName;以及 src/Greenshot/Destinations/EmailDestination.cs:
private static readonly bool HasMapiClient; private static readonly string MapiClient;注意公有静态属性MapiClient、Log使用 PascalCasing,私有/内部字段使用_camelCase,前缀与大小写规则配合使用,一眼即可区分作用域。
规范 12:常量使用 PascalCasing
所有常量局部变量与字段使用 PascalCasing。唯一例外是interop 代码:此时常量值必须与所调用的外部代码的名称和值完全一致。典型例子见 src/Greenshot/Ai/AiToolCaller.cs:
private static readonly Guid WinTrustActionGenericVerifyV2 = new Guid("00AAC56B-CD44-11d0-8CC2-00C04FC295EE");该 GUID 是 Windows WinTrust API 的常量,因此保留其原生命名(尽管遵循 readonly 与 PascalCasing,但作为 interop 常量,值不可改写)。
规范 4:避免this.
除非绝对必要(如与参数/局部变量产生歧义),否则不写this.。这与规范 3 的_前缀互为补充:_camelCase本身就足以区分字段与参数,this.显得冗余。
规范 16:不使用标签
禁止goto等标签用法,保持控制流清晰。
四、修饰符与可见性
规范 5:总是显式指定可见性
即使某个成员恰好是默认可见性,也必须显式写出:
// 正确:显式写出 private private string _foo; // 错误:依赖默认可见性 string _foo;同时,可见性必须是第一个修饰符:写public abstract,而不是abstract public。类似地,前文提到的static readonly顺序也遵循"先类别、后能力"的原则。
五、类型与表达式写法
规范 10:谨慎使用var
只有变量类型一目了然时才允许var。文档给出的正例是var stream = new FileStream(...)(右侧new显式声明类型);反例是var stream = OpenStandardInput()(类型由方法推断,不直观)。源码实证见 src/Greenshot/Ai/AiToolCaller.cs:
using var certificate = new X509Certificate2(X509Certificate.CreateFromSignedFile(filePath));右侧显式new,类型清晰,符合规范。
规范 11:使用语言关键字而非 BCL 类型
类型引用与方法调用统一使用 C# 语言关键字:int、string、float代替Int32、String、Single;方法调用写int.Parse而非Int32.Parse。实证见 src/Greenshot/Destinations/EmailDestination.cs:
string mapiClientHkcu = RegistryHive.CurrentUser.ReadKey(@"Clients\Mail"); string mapiClientHklm = RegistryHive.LocalMachine.ReadKey64Or32(@"Clients\Mail");规范 13:优先使用nameof(...)
凡能用nameof表达字符串的地方,不用手写"..."字符串,以避免重命名时字符串失同步。实证见 src/Greenshot/Capturing/CaptureKeyRegistry.cs:
throw new ArgumentNullException(nameof(binding)); throw new ArgumentException($"{binding.Key} can only be used together with another key", nameof(binding));以及 src/Greenshot/Ai/AiWindowRefs.cs 的throw new ArgumentNullException(nameof(client));。
规范 14:字段置于类型声明顶部
所有字段必须集中在类型声明的最前面,便于一眼看到类型的状态。
规范 15:非 ASCII 字符使用 Unicode 转义序列
源码中的非 ASCII 字符一律写\uXXXX转义序列,而非字面字符——字面字符可能被某些工具或编辑器弄乱编码。
六、文件组织与其他细则
规范 6:命名空间导入置于文件顶部、namespace 声明之外,并按字母排序
即 using 指令放在最上方、namespace块外部,且按字母顺序排列。实证见 src/Greenshot/Helpers/GreenshotCommandLine.cs:System系列、System.CommandLine、System.Linq、System.Runtime.CompilerServices、Dapplo.Windows.Kernel32、Greenshot.Ipc.Cli依序排列,全部位于namespace Greenshot.Helpers之外。
规范 9:已有文件的既有风格优先
这是最重要的一条"兜底"规则:如果某个文件的历史代码与本文规范不一致(例如私有成员历史上叫m_member而非_member),该文件的既有风格优先。贡献者不应为了新规范顺手重构整个旧文件,否则会制造大量无意义 diff;风格迁移应在专门的重构提交中单独进行。
七、从源码看规范的落地
以下代码摘自 src/Greenshot/Helpers/GreenshotCommandLine.cs,可以在一小段真实代码中同时看到多条规范的协同:
internal static class GreenshotCommandLine { private static readonly Option<bool> NoRunOption = new Option<bool>("--no-run") { Description = "Exit immediately without starting or showing Greenshot." }; private static readonly Option<string> LanguageOption = new Option<string>("--language") { HelpName = "language-code", Description = "Set the UI language for Greenshot (e.g. en-US, de-DE) and save the configuration." };对照检查:
- 大括号 Allman 风格、块体独立缩进(规范 1、2);
- 字段
_前缀 +static readonly顺序(规范 3); - 私有静态字段
private static readonly显式可见性且可见性在前(规范 5); var只用于右侧new明确类型的场景(规范 10);- 字段全部置于类型顶部(规范 14);
- 命名空间导入按字母序置于 namespace 外(规范 6)。
八、工具链保障:构建系统如何强制执行规范
Greenshot 不止在文档层面倡导风格,还在构建系统中配置了自动检查。见 src/Directory.Build.props:
<EnableNETAnalyzers>true</EnableNETAnalyzers> <PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" ... /> <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" ... /> <AdditionalFiles Include="$(MSBuildThisFileDirectory)BannedSymbols.txt" Link="BannedSymbols.txt" />.NET Analysers与Microsoft.VisualStudio.Threading.Analyzers在编译期对异步与线程相关 API 的误用给出诊断;Microsoft.CodeAnalysis.BannedApiAnalyzers结合 src/BannedSymbols.txt 直接禁止一批危险 API 的调用,例如Thread.Sleep(要求改为await Task.Delay)、Task.Wait/Task.Result(要求 await)、SynchronizationContext.Send与Control.Invoke(要求通过IUiDispatcher.InvokeAsync到达 UI 线程)、Task.Run只允许在文档化的边界(flow runner、AsyncCommand 或标注// PARALLEL:的分支)使用等。这些规则在 docs/async-threading-roadmap.md 中有详细设计说明。
这意味着:贡献者提交的代码如果违反这些硬性 API 约束,CI 构建阶段就会失败,属于"编译期可验证"的规范;而命名、缩进等风格规范则依赖代码评审(PR review)把关。
九、AI 辅助贡献政策
CONTRIBUTING.md 明确欢迎使用 AI 工具(如 Claude、GitHub Copilot、Gemini)辅助编写的贡献,但要求与其他贡献遵守完全相同的规则:
- 责任主体是提交 PR 的人:贡献者须理解变更、已自行审查并测试,并能回答关于该变更的提问。AI 只是工具,不减轻人的责任。
- CLA 由人签署并覆盖 AI 部分:Contributor License Agreement(贡献者许可协议)由提交者本人签署,覆盖 AI 辅助编写的部分。AI 工具自身无法签署 CLA,因此由 AI 账户(如
claude)直接提交的 commit 会被放入 CLA 白名单(allowlist),由提出该提交的维护者或贡献者背书覆盖。 - 保持透明:在 PR 中明确说明使用了 AI 工具,并保留工具自动添加的作者归属信息(如
Co-Authored-By:行),以便评审者知晓所审内容的来源。 - 只提交有权提交的内容:不得提交 AI 从不兼容许可证的来源复制的任何内容,防止许可证污染。
- 编码规范同样适用于 AI 写的代码:前文 16 条风格规则对 AI 生成的代码一视同仁,提交前应逐条自查。
十、贡献工作流:从构建环境到提交
结合 README.md 的开发者指引,向 Greenshot 贡献的典型流程如下:
环境准备(README 明确列出):
- Windows 操作系统环境;
- Visual Studio 2026(原生项目使用 v145 C++ 工具集),需包含Desktop development with C++工作负载、MSVC v145 x64/x86 构建工具与 Windows 10 SDK;
- .NET SDK 10.0.100 或更新(Greenshot.Mcp 面向 .NET 10);
- .NET Framework 4.8 Developer Pack / targeting pack。
构建:
- 图形界面:打开 src/Greenshot.sln,Build → Build Solution;
- 命令行:使用 MSBuild 而非
dotnet build:
msbuild src\Greenshot.sln /p:Configuration=Debug /t:Build /v:minimal解决方案提供 Debug(默认,含主程序、插件、greenshot-cli、greenshot-proxy、greenshot-mcp 与测试)、Release(额外产出校验和、SBOM、Greenshot Light 与安装包)、Debug Light / Release Light(仅 Greenshot Light 主程序)等配置,详见 README.md。
提交前自查(建议按 CONTRIBUTING.md 逐条核对):
- 大括号为 Allman 风格,四空格缩进,无游离空格、无多余空行;
- 字段
_camelCase(s_/t_对应静态/线程静态),尽量readonly且顺序为static readonly; - 可见性显式且位于修饰符第一位,避免多余
this.; var仅在右侧类型明确时使用;类型与方法调用使用语言关键字;- 常量 PascalCasing(interop 常量除外);能写
nameof(...)不写字符串; - using 置于 namespace 外并按字母序;字段集中在类型顶部;
- 非 ASCII 字符使用
\uXXXX;不使用 goto 标签; - 若修改旧文件,尊重该文件既有风格(规范 9);
- 若使用 AI 辅助:PR 中声明、保留
Co-Authored-By:归属、确认内容来源可提交,并由本人签署 CLA、对变更负责。
结语
CONTRIBUTING.md 篇幅不长,却精确刻画了 Greenshot 代码库的"体质":以 Visual Studio 默认风格为基调,以_camelCase命名与显式可见性等硬规则保证多项目协作的一致性,以nameof、语言关键字、Banned API 分析器等实践降低重构成本与并发风险,并对 AI 辅助贡献给出责任清晰、开放包容的准入规则。对新贡献者而言,这份文档既是代码风格字典,也是提交前的最终自检清单。
- 桌面应用
- 图像处理
【免费下载链接】greenshot
Greenshot for Windows - for more information look here:
相关推荐
UTM 开源贡献指南解读:代码规范、设计哲学与 AI 辅助贡献流程
UTM 开源贡献指南解读:代码规范、设计哲学与 AI 辅助贡献流程 本篇指南以 UTM(Virtual machines for iOS and macOS)仓
虚拟化llama.cpp 贡献指南:贡献者分级、AI 使用政策、PR 流程与 C/C++ 编码规范全解
llama.cpp 贡献指南:贡献者分级、AI 使用政策、PR 流程与 C/C++ 编码规范全解 本文以 llama.cpp 仓库的 CONTRIBUTING.
人工智能大模型模型推理服务推理引擎本地部署后端CANN/asc-devkit内存消毒样例
msSanitizer样例说明 概述 msSanitizer用于检测Ascend C样例运行过程中的内存访问、内存泄漏、未使用内存、竞争和未初始化访问等异常。本
人工智能深度学习算子库CANNAscend
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考