C#中如何在一个using别名中使用其他using别名作为类型参数

9

我正在尝试在我的C#程序顶部定义一对类型别名。以下是我所尝试的简短示例:

using System;
using System.Collections.Generic;

namespace Foo {
    using TsvEntry = Dictionary<string, string>;
    using Tsv = List<TsvEntry>;
}

当我尝试使用mcs 3.2.8.0编译此代码时,出现以下错误信息:
foo.cs(6,19): error CS0246: The type or namespace name `TsvEntry' could not be found. Are you missing an assembly reference?

在C#中,是否可以在其他别名中使用“using”别名,或者我对“using”语句的工作方式存在误解?
6个回答

8

请查看此问题的文档:

https://msdn.microsoft.com/zh-cn/library/aa664765(v=vs.71).aspx

文档中指出:

The order in which using-alias-directives are written has no significance, and resolution of the namespace-or-type-name referenced by a using-alias-directive is not affected by the using-alias-directive itself or by other using-directives in the immediately containing compilation unit or namespace body. In other words, the namespace-or-type-name of a using-alias-directive is resolved as if the immediately containing compilation unit or namespace body had no using-directives. In the example

namespace N1.N2 {}
namespace N3
{
   using R1 = N1;         // OK
   using R2 = N1.N2;      // OK
   using R3 = R1.N2;      // Error, R1 unknown
}

the last using-alias-directive results in a compile-time error because it is not affected by the first using-alias-directive.

从技术上讲,你不能在同一命名空间中这样做,但如果你在命名空间1中使用别名,并在嵌套的命名空间中为此别名使用别名,它将起作用:

namespace N1
{
    namespace N12 { }
}

namespace N2
{
    using R1 = N1;

    namespace N2
    {
        using R2 = R1.N12;
    }
}

我并不确定在你的具体示例中使用别名是否值得,尽量避免使用,主要是为了解决命名空间冲突。


4
作为对其他答案的补充,如果您真的想继续这个方式,嵌套命名空间是正确的方式。因为第二个命名空间的第一个使用将被定义。以下内容可以工作,因为您在更深层的命名空间中:
namespace N1
{
    using TsvEntry = Dictionary<string, string>;

    namespace N1.N2
    {
        using Tsv = List<TsvEntry>;

    }
}

请注意,虽然这段代码能正常工作,但我不建议使用这种代码结构,因为可能会导致嵌套代码过深。

3

来自MSDN的使用别名指令:

编写using-alias-directives的顺序没有意义,并且using-alias-directive引用的命名空间或类型名称的解析不受using-alias-directive本身或立即包含编译单元或命名空间体中的其他using-directives的影响。换句话说,使用别名指令的命名空间或类型名称的解析就好像立即包含编译单元或命名空间体没有using-directives。

// 强调是我的

在您的示例中,最后一个using-alias-directive会导致编译时错误,因为它不受第一个using-alias-directive的影响。


2
正如其他人提到的那样,以这种方式使用别名是不可能的,但是,您可以使用类继承获得类似的功能。
使用您的示例,您可以像这样做:
using System;
using System.Collections.Generic;

namespace Foo {
    class TsvEntry : Dictionary<string, string> {}
    class Tsv : List<TsvEntry> {}
}

这样做的另一个好处是,随着需要,您可以轻松地为这些类添加额外的功能。

1

我将这里添加,因为当我搜索相关问题时,经常遇到此问题,可能会帮助其他人。

如果您想要在函数式编程中使用函数别名,您需要使用delegate关键字。您可以将delegate视为创建接口,但是用于函数。

所以,代替: using Expression = Func<string>; using Converter = Func<List<string>, Expression>; 您可以使用: delegate string Expression(); delegate Expression Converter(List<string> tokenizedExpressions);

https://weblogs.asp.net/dixin/functional-csharp-function-type-and-delegate


0

与其使用 Foo 作为命名空间,你可以遵循建议,包括公司名称和例如产品名称。你最终会得到一个类似 Fabrikam.Math 的命名空间。这样做不再看起来像是嵌套只为达到别名的目的:

using System;
using System.Collections.Generic;
namespace Fabrikam
{
    using TsvEntry = Dictionary<string, string>;
    namespace Math
    {
        using Tsv = List<TsvEntry>;
        internal class Program
        {
            static void Main()
            {
                var list = new Tsv();
                Console.WriteLine($"Number of elements: {list.Count}");
                Console.ReadLine();
             }
         }
    }
}

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