【问题标题】:In C# when is the var keyword different from typing it out?在 C# 中,var 关键字何时与键入不同?
【发布时间】:2010-09-28 08:01:04
【问题描述】:

C# 3.0 引入了var 关键字。编译后,编译器将为您插入正确的类型。这意味着它甚至可以在 2.0 运行时上运行。到目前为止,一切都很好。但是前几天我发现了一个例子,var 关键字将被替换为对象,因此不够具体。假设你有类似的东西:

var data = AdoMD.GetData(...); // GetData returns a DataTable

foreach (var row in data.Rows)
{
     string blah = (string)row[0]; // it fails since it's of type object
}

当我尝试同时使用IntelliSense 时,编译器告诉我它是对象类型。 data.Rows 的类型为 System.Data.DataRowCollection。以下作品:

var data = AdoMD.GetData(...); // GetData returns a DataTable

foreach (DataRow row in data.Rows)
{
     string blah = (string)row[0]; // works since it now has the right type
}

这不是关于var使用的问题,here有一个线程。

我正在使用 Visual Studio 2008 SP1 顺便说一句。

编辑:现在附上了正确的代码。

【问题讨论】:

  • 你能把你的代码贴在这里吗?
  • 之所以如此,是因为这段代码是在 2.0 之前的早期编写的,那时还没有泛型。那时我们都使用 ArrayList 而不是强类型 List
  • var 如果在当前作用域的某个地方定义了一个 'var' 类,也会有所不同(因为它会覆盖关键字的使用),尽管这是相当病态的,并且通常会导致各种编译错误.

标签: c# var


【解决方案1】:

我想我看到了问题所在。 DataRowCollection 是非泛型的,因此编译器唯一知道的是它包含 Object 类型的对象。如果它是一个通用的数据结构,这将是可行的。

【讨论】:

  • 因为这段代码是在 2.0 之前的早期编写的,那时还没有泛型。
【解决方案2】:

这个:

using System;

namespace Test
{
    public class X
    {
        public String Bleh;
    }

    public class Y : X
    {
        public String Blah;
    }

    public static class Program
    {
        public static void Main()
        {
            var y = SomeFunctionThatReturnsY();
            // y. <-- this gives me both Blah and Bleh in the dropdown
        }

        public static Y SomeFunctionThatReturnsY()
        {
            return new Y();
        }
    }
}

按预期工作,它让我在 Visual Studio 2008 中显示 Bleh 和 Blah 的智能感知。

你有类似的东西,或者正是吗?除了您显示的代码之外,可能还有其他事情会触发智能感知。

回答实际问题。拼出类型和使用var 之间的唯一区别是,在某些情况下,当您根本没有正确的类型时,您必须使用 var。如果我没记错的话,这仅在您使用匿名类型时才相关。

没有其他区别,编译器会在左侧选择与右侧相同的类型。

编辑:感谢@Telos 指出一个区别是,当使用 var 时,您当然必须在声明时给变量一个值,因为右侧用于指示左侧变量的类型。在拼写类型时,您当然可以选择不给它一个值。

【讨论】:

  • 其实还有一个区别,就是var必须在声明时初始化。
【解决方案3】:

我的猜测是 somethingThatReturnsY 实际上声明返回 X - 即使它在实践中返回 Y。我希望如果您将y 声明为Y y = somethingThatReturnsY();,它将无法编译。

var 的规则非常简单(对于适用的情况 - 有各种限制阻止您执行 var x = null; 等。

如果您认为var 确实做错了事,请发布一个简短但完整的程序来演示。

【讨论】:

    【解决方案4】:

    我尝试在控制台应用程序中使用以下代码重现这一点。

    class Program
    {
        static void Main(string[] args)
        {
            var j = returny();
            j.blah();
        }
    
        private static y returny()
        {
            return new y();
        }
    }
    
    class x
    {
    }
    
    class y : x
    {
        public void blah() { }
    }
    

    这按预期工作,IntelliSense 是正确的,Reflector 表明 j 的类型为 y。我的猜测是,如果您遇到可疑的事情,那么这里的简单情况会更复杂。

    我也在使用 Visual Studio 2008 RTM。

    【讨论】:

      【解决方案5】:

      DataTable.Rows 返回实现 InternalDataCollectionBase 的 DataRowCollection,后者又实现 ICollection 和 IEnumerable。代码

      foreach(DataRow row in dt.Rows) { }
      

      将 DataRowCollection 中的每个项目转换为 DataRow。您可以通过将其更改为来证明这一点

      foreach(int row in dt.Rows) { }
      

      编译但抛出 InvalidCastException。

      如果 DataRowCollection 实现了IEnumerable&lt;DataRow&gt;,那么它将无法编译,使用 var 会将列表中的每个对象都键入为 DataRow。

      【讨论】:

        【解决方案6】:

        我认为您在示例代码中没有提供足够的信息。我做了一个小程序来尝试模仿你描述的行为:

        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
        
            private void button1_Click(object sender, EventArgs e)
            {
                var y = SomeFunctionThatReturnsY();
        
                MessageBox.Show(y.bla);
        
                return;
            }
        
            private Y SomeFunctionThatReturnsY()
            {
                return new Y();
            }
        }
        
        internal class X { }
        
        internal class Y : X
        {
            public string bla = "Saw a Y, not an X";
        }
        

        但输出清楚地表明 var 解析的是 Y 类型,而不是 X。

        您确定您的函数返回 Y 作为 Y 引用,而不是作为 X 引用?

        【讨论】:

          【解决方案7】:

          它可以正常工作。当编译器无法确定正确的数据类型时,它会将对象类型作为“对象”。

          【讨论】:

            【解决方案8】:

            当您使用 foreach 关键字时,可以通过 IEnumerable 接口访问 DateRowCollection。用于访问 DataRow 的特定方法称为 Current 并返回一个对象。所以 var 关键字是看 Current 方法的返回值来推断类型。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-09-04
              • 2011-04-03
              • 2010-11-11
              • 1970-01-01
              • 2010-11-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多