为什么C#处理命令行参数不一致?

8
在C#中,直接从Main()获取命令行参数会省略exe名称,这与C的传统相反。通过Environment.GetCommandLineArgs获取相同的命令行参数则包括它。
我是否错过了一些好的逻辑原因来解释这种明显的不一致性?
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(string.Format("args.Length = {0}", args.Length));

        foreach(string arg in args)
        {
            Console.WriteLine(string.Format("args = {0}", arg));
        }

        Console.WriteLine("");

        string[] Eargs = Environment.GetCommandLineArgs();
        Console.WriteLine(string.Format("Eargs.Length = {0}", Eargs.Length));
        foreach (string arg in Eargs)
        {
            Console.WriteLine(string.Format("Eargs = {0}", arg));
        }

    }
}

输出:

C:\\ConsoleApplication1\ConsoleApplication1\bin\Debug>consoleapplication1 xx zz aa 
args.Length = 3 
args = xx
args = zz 
args = aa
Eargs.Length = 4 
Eargs = consoleapplication1 
Eargs = xx 
Eargs = zz 
Eargs = aa

首先,它不是C#,而是.NET框架。 - Andrey
5
这并不矛盾,只是两种不同的工作方法。前者不返回可执行文件,而后者则会。它们有不同的用途。 - Daniel DiPaolo
1
并且它已经记录在http://msdn.microsoft.com/en-us/library/acy3edy3.aspx中。 - Andrey
3个回答

15
因为它不是C语言,因此没有与其约定绑定。需要exe名称几乎是一个边缘情况;在我需要它的少数情况下(与其他参数相比),我认为省略它是合理的决定。此外,在规范中(ECMA334v4,§10.1)要求这样做;(剪辑到相关部分):“10.基本概念”、“10.1应用程序启动”......此入口点方法始终命名为“Main”,并且应该具有以下签名之一:
static void Main() {…} 
static void Main(string[] args) {…} 
static int Main() {…} 
static int Main(string[] args) {…} 

• 假设参数的名称为args。如果由args指定的数组的长度大于零,则数组成员args [0]args [args.Length-1](包括)应引用称为应用程序参数的字符串,这些字符串在应用程序启动之前由主机环境给出实现定义的值。其目的是从托管环境中的其他位置确定应用程序在应用程序启动之前要提供的信息。如果主机环境无法提供同时具有大写和小写字母的字符串,则实现应确保以小写形式接收字符串。
[注意:在支持命令行的系统上,应用程序参数对应于通常称为命令行参数的内容。结束注意]


2
他们给了你获取它的方法(实际上有几种)。 - jcolebrand
我认为这个问题仍然有效。为什么要区分args数组和Environment.GetCommandLineArgs()的结果。忘记C语言,为什么这两种方法会有差异? - BFree
@drachenstern:好的,说得对。但是仅仅因为“这不是C语言”并不能真正回答问题。 - BFree
@drachenstern:没问题,这样也可以。我只是想指出的是,“这不是C语言”并不能真正回答他的问题。也许这个问题我们都无法回答,那么是的,在这里问这个问题是没有意义的,但这应该成为答案。</beating_dead_horse> - BFree
我很震惊这个回答一直被点赞。它根本没有回答问题。“这不是C”完全无关紧要。“省略它的决定”也错了。它在文档中提到并不重要。难道我真的表达不清楚,没有人理解问题实际上是什么吗?Waleed至少理解了问题,并强调了他的回答是主观的,尽管我认为他的解释不够令人满意。 - MickeyfAgain_BeforeExitOfSO
显示剩余12条评论

8

我的困难不在于它是否被视为命令行参数 - 无论哪种方式,我都可以接受。我的困难在于一种情况下它是,而在另一种情况下它不是。 - MickeyfAgain_BeforeExitOfSO
有趣的引言,直到一个名为GetCommandLineArgs()的函数将程序名称视为第一个命令行参数。 - cdkMoose

6
对我而言,两种方法返回不同结果的原因在于Context
  • Environment类用于操作当前环境和进程,因此Environment.GetCommandLineArgs();返回可执行文件名称是有意义的,因为它是进程的一部分。

  • 至于args数组,对我而言,排除可执行文件名称是有意义的。我知道我正在调用可执行文件,并且在运行我的应用程序的上下文中,我想知道发送给它的参数。

归根结底,拥有获取这两个选择的方法非常强大。


1
+1 我正在回答问题时看到了这些帖子,这正是我要提到的,这完全取决于调用的视角(上下文)。 - curtisk
人们过去常常根据可执行文件的名称来进行技巧性操作,因为它包含在参数列表中以改变执行路径。如果文件名为move.exe,则默认移动文件;如果是copy.exe,则默认复制文件,依此类推。这是一些愚蠢的编译器技巧,但仍然被使用。 - jcolebrand
那些不是编译器技巧,而是运行时的,但无论如何,我的观点仍然成立。 - jcolebrand

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接