Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么不是';难道没有一种隐含的类型吗?_C# - Fatal编程技术网

C# 为什么不是';难道没有一种隐含的类型吗?

C# 为什么不是';难道没有一种隐含的类型吗?,c#,C#,我想我理解为什么这个小型C#控制台应用程序无法编译: using System; namespace ConsoleApp1 { class Program { static void WriteFullName(Type t) { Console.WriteLine(t.FullName); } static void Main(string[] args) {

我想我理解为什么这个小型C#控制台应用程序无法编译:

using System;

namespace ConsoleApp1
{
    class Program
    {
        static void WriteFullName(Type t)
        {
            Console.WriteLine(t.FullName);
        }

        static void Main(string[] args)
        {
            WriteFullName(System.Text.Encoding);
        }
    }
}
编译器引发CS0119错误:
“Encoding”是在给定上下文中无效的类型。我知道我可以使用
typeof()
操作符从类型对象的名称生成类型对象:

        ...
        static void Main(string[] args)
        {
            WriteFullName(typeof(System.Text.Encoding));
        }
        ...
一切都按预期进行

但对我来说,
typeof()
的使用似乎总是有些多余。如果编译器知道某个标记是对给定类型的引用(如错误CS0119所示),并且它知道某个赋值的目标(无论是函数参数、变量还是其他)需要对给定类型的引用,那么为什么编译器不能将其视为隐式
typeof()
调用

或者,编译器完全有能力执行这一步骤,但由于可能产生的问题,它被选择不执行。这是否会导致我现在无法想到的任何歧义/易读性问题

如果编译器知道某个标记是对给定类型的引用(如错误CS0119所示),并且它知道某个赋值的目标(无论是函数参数、变量还是其他)需要对给定类型的引用,为什么编译器不能将其作为隐式typeof()调用

首先,您的建议是编译器同时考虑“从内到外”和“从外到内”。也就是说,为了使您建议的功能正常工作,编译器必须推断表达式
System.Text.Encoding
引用了一个类型,并且上下文(调用
writevelname
)需要一个类型我们如何知道上下文需要类型
writeFileName
的解析需要重载解析,因为可能有一百个解析,并且可能只有一个解析将
类型
作为该位置的参数

所以现在我们必须设计重载解析来识别这个特定的情况。过载解决已经够难了。现在还要考虑对类型推断的影响。

C#的设计使得在绝大多数情况下,您不需要进行双向推理,因为双向推理既昂贵又困难。我们使用双向推理的地方是lambdas,我花了一年的大部分时间来实现和测试它。在lambdas上获得上下文敏感推理是使LINQ工作所必需的一个关键特性,因此获得正确的双向推理是值得的

此外:
类型为什么特别?说
objectx=typeof(T)是完全合法的所以不应该
对象x=int在您的提案中是否合法?假设类型
C
具有用户定义的从
type
C
的隐式转换;不应该
C=string合法吗

但是让我们暂时搁置一下,考虑一下你的建议的其他优点。例如,您打算对此做些什么

class C {
  public static string FullName = "Hello";
}
...
Type c = C;
Console.WriteLine(c.FullName); // "C"
Console.WriteLine(C.FullName); // "Hello"
你觉得
c==c
但是
c.FullName!=C.全名
?编程语言设计的一个基本原则是,可以将表达式填充到变量中,变量的值的行为与表达式类似,但这里根本不是这样

你的建议基本上是,每一个引用类型的表达式都有不同的行为,这取决于它是被使用还是被分配的,这是非常令人困惑的

现在,您可能会说,好吧,让我们用一种特殊的语法来消除使用类型的情况与提到类型的情况之间的歧义,有这样一种语法。它是(T)类型的
typeof
!如果我们想把
T.FullName
看作
T
Type
我们说
typeof(T).FullName
如果我们想把
T
看作是查找中的限定符,我们说
T.FullName
,现在我们已经清楚地消除了这些情况的歧义,而不必做任何双向推断

基本上,基本问题是类型不是C#中的第一类。有些事情只能在编译时对类型执行。没有:

Type t = b ? C : D;
List<t> l = new List<t>();
因为
C.M
根本没有任何成员。所以这个问题消失了。我们从不说“好吧,
C.M
可转换为
Action
Action
有一个方法
Invoke
,所以让我们允许
C.M.Invoke()
。这不会发生。同样,方法组不是第一类值。只有在它们转换为委托之后,它们才会成为第一类值

基本上,方法组被视为具有值但没有类型的表达式,然后可转换性规则确定哪些方法组可转换为哪些委托类型

现在,如果你要提出一个方法组,应该隐式地转换为<代码>方法信息> />代码,并在任何一个被期望为<代码>方法信息>代码的上下文中使用,那么我们就必须考虑它的优点。几十年来提出了一个建议:<代码>信息> <代码>操作符(发音为Foof)。“当然!)当给定一个方法组时,它将返回一个

MethodInfo
,当给定一个属性时,它将返回一个
PropertyInfo
,以此类推,而该方案总是失败,因为设计工作太多,效益太少
nameof
是实现该版本的最便宜的方法


一个你没有问但似乎有密切关系的问题:

您说过
C.FullName
可能不明确,因为不清楚
C
类型还是
C
类型。C#中是否存在其他类似的歧义

对!!考虑:

enum Color { Red }
class C {
  public Color Color { get; private set; }
  public void M(Color c) { }
  public void N(String s) { }
  public void O() {
    M(Color.Red);
    N(Color.ToString());
  }
}
在这种情况下,巧妙地称为“颜色问题”,
enum Color { Red }
class C {
  public Color Color { get; private set; }
  public void M(Color c) { }
  public void N(String s) { }
  public void O() {
    M(Color.Red);
    N(Color.ToString());
  }
}