代码之家  ›  专栏  ›  技术社区  ›  Anders Rune Jensen

在C中,什么时候var关键字不同于输入它?

  •  2
  • Anders Rune Jensen  · 技术社区  · 16 年前

    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
    }
    

    当我试图同时使用row时 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 BTW。

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

    8 回复  |  直到 14 年前
        1
  •  10
  •   Anders Rune Jensen    14 年前

    我想我看到了问题。DataRowCollection是非泛型的,因此编译器只知道它包含Object类型的对象。如果它是一个通用的数据结构,那么就可以工作了。

        2
  •  3
  •   Community Mr_and_Mrs_D    7 年前

    这是:

    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的IntelliSense。

    你有什么东西吗 喜欢 或者,或者 确切地 那?可能还有其他事情比您显示的代码更让IntelliSense感到困惑。

    回答实际问题。拼写出类型和使用 var ,在某些情况下是你吗? 必须 当您没有正确的类型时,使用var。如果我没弄错的话,这只在您使用匿名类型时才相关。

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

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

        3
  •  2
  •   Jon Skeet    16 年前

    我猜是这样的 somethingThatReturnsY 实际上是 宣布 返回x-即使实际返回y。我想如果你申报的话 y 作为 Y y = somethingThatReturnsY(); 它将无法编译。

    规则 var 非常简单(对于它起作用的情况-有各种各样的限制来阻止你这样做 var x = null; 等。

    如果你认为 var 真的是做错事了,请张贴一个简短但完整的程序来演示。

        4
  •  1
  •   Peter Mortensen peter karasev    14 年前

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

    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
  •  1
  •   Jamie Ide    14 年前

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

    foreach(DataRow row in dt.Rows) { }
    

    将DataRowCollection中的每个项强制转换为DataRow。您可以通过将其更改为

    foreach(int row in dt.Rows) { }
    

    它编译但抛出一个无效的castexception。

    如果实现了DataRowCollection IEnumerable<DataRow> 然后,如果不编译和使用var,则会将列表中的每个对象作为数据行键入。

        6
  •  0
  •   Greg D    16 年前

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

    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
  •  0
  •   Perry Neal    16 年前

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

        8
  •  0
  •   Jeff Hornby    14 年前

    使用foreach关键字时,将通过IEnumerable接口访问DateRowCollection。用于访问数据行的特定方法称为current,并返回一个对象。所以var关键字查看当前方法的返回值来推断类型。