C#控制台应用程序入口点的 minimal 样板代码是什么?它将使行为良好的公民?
当有人使用Visual Studio创建控制台应用程序项目时(截至撰写本文时为2008年),您将看到一个样板Program.cs
,如下所示:
class Program
{
static void Main(string[] args)
{
}
}
然而,每个人都需要做一些事情来使控制台应用程序成为最低好公民。例如,如果发生异常,则将清除消息写入标准错误(Console.Error)而不是标准输出(Console.Out)。同样,如果发生某些错误,请将错误代码设置为非零值,以便调用进程可以检测到失败。
C#控制台应用程序入口点的 minimal 样板代码是什么?它将成为行为良好的公民?您将添加或更改以下内容?
using System;
using System.Diagnostics;
using System.Linq;
static class Program
{
static void Run(string[] args)
{
// TODO Replace line-echoing sample with actual application code
string line;
while ((line = Console.ReadLine()) != null)
Console.WriteLine(line);
}
static int Main(string[] args)
{
// TODO Use a more robust arguments parser
if (args.Any(arg => arg.Equals("/v") || arg.Equals("-v"))) // verbose?
Trace.Listeners.Add(new ConsoleTraceListener(true));
try
{
Run(args);
return Environment.ExitCode;
}
catch (Exception e)
{
Console.Error.WriteLine(e.Message);
Trace.TraceError(e.ToString());
return Environment.ExitCode != 0
? Environment.ExitCode : 100;
}
}
}
这个样板实现了什么:
Program
class is static 此问题的非目标:
答案 0 :(得分:7)
我认为一切都取决于该应用的实际要求。如果没有要求进行自定义错误处理 - 请不要这样做。如果没有程序需要检查您的应用程序的退出代码 - 无需返回它;我认为有些情况不适用这些要求。
换句话说,最小化是最小的;做最可能有效的事情。如果你的应用程序符合要求,我想我们可以称之为良好的行为。
答案 1 :(得分:3)
对我来说,我希望看到Run(args)
替换为类的实例化。类似的东西:
主要尝试:
try
{
// Process args to get parameters for AClass
AClass program = new AClass(a, b);
return program.Run();
}
<强> ACLASS:强>
public class AClass {
AClass(string a, string b) { ... }
public int Run() {
...
return Environment.ExitCode;
}
}
这样的事情会阻碍程序代码并鼓励创建面向对象的方法。
关于AClass()
构造函数,我认为参数应该在传递到AClass()
之前进行处理,而不是AClass()
必须知道它是通过控制台应用程序创建的。< / p>
答案 2 :(得分:2)
关于这个问题,我发现这篇文章是最深入和最有用的:
.NET中的控制台应用程序,或者教授新的老狗伎俩
迈克尔布鲁克MSDN Magazine 2004年2月
答案 3 :(得分:0)
我使用emacs和名为defaultcontent.el的东西。如果您不熟悉,Emacs是一个文本编辑器,并且非常易于扩展。 defaultcontent.el是一个扩展,它将默认内容插入(惊讶)新文件,当它们由emacs首次创建时。
因此,如果我尝试打开一个不存在的.cs文件,emacs会创建它,然后将一堆默认内容放入其中。我决定在新文件中包含哪些内容。对于我的C#文件,此内容包括:
defaultcontent.el还允许我将光标定位在我想要的位置。就我而言,那是在空的Run()方法的中间。
这是我的默认内容:
// default.cs
// ------------------------------------------------------------------
//
// Description goes here....
//
// Author: MyUser
// built on host: MyMachine
// Created Tue Oct 27 15:01:18 2009
//
// last saved:
// Time-stamp: <2009-October-20 00:18:52>
// ------------------------------------------------------------------
//
// Copyright Notice here
// All rights reserved!
//
// ------------------------------------------------------------------
using System;
using System.Reflection;
// to allow fast ngen
[assembly: AssemblyTitle("default.cs")]
[assembly: AssemblyDescription("insert purpose here")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Dino Chiesa")]
[assembly: AssemblyProduct("Tools")]
[assembly: AssemblyCopyright("Copyright notice again")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.1.1.1")]
namespace Cheeso.ToolsAndTests
{
public class default
{
// ctor
public default () {}
string _positionalParam1;
string _param1;
int _intParam = DefaultIntParamValue;
bool _flag1;
private readonly int DefaultIntParamValue = -99;
// ctor
public default (string[] args)
{
for (int i=0; i < args.Length; i++)
{
switch (args[i])
{
case "-stringArg":
i++;
if (args.Length <= i) throw new ArgumentException(args[i]);
_param1 = args[i];
break;
case "-intArg":
i++;
if (args.Length <= i) throw new ArgumentException(args[i]);
if (_intParam != DefaultIntParamValue)
throw new ArgumentException(args[i]);
if (args[i].StartsWith("0x"))
_intParam = System.Int32.Parse(args[i].Substring(2), System.Globalization.NumberStyles.AllowHexSpecifier );
else
_intParam = System.Int32.Parse(args[i]);
break;
case "-boolarg":
_flag1 = true;
break;
case "-?":
throw new ArgumentException(args[i]);
default:
if (_positionalParam1 != null)
throw new ArgumentException(args[i]);
_positionalParam1 = args[i];
break;
}
}
// default values
if (_positionalParam1 == null)
_positionalParam1 = "default.value.for.positional.param";
if (_param1 == null)
_param1 = "default.value.for.param1";
if (_param2 == 0)
_param2 = DEFAULT_value_for_param2;
}
public void Run()
{
}
public static void Usage()
{
Console.WriteLine("\ndefault: <usage statement here>.\n");
Console.WriteLine("Usage:\n default [-arg1 <value>] [-arg2]");
}
public static void Main(string[] args)
{
try
{
new default(args)
.Run();
}
catch (System.Exception exc1)
{
Console.WriteLine("Exception: {0}", exc1.ToString());
Usage();
}
}
}
}
我还为.c,.cpp,.vb,.csproj,.xml,.xsd,.wsdl,makefile和许多其他文件类型设置了defaultcontent。