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
}

当我尝试使用行既智能感知和编译器告诉我,这是型对象。 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
}

这不是关于变种的使用问题,存在对一个线程这里

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

编辑:正确的代码现在附

有帮助吗?

解决方案

我想我看到的问题。 DataRowCollection是不通用的,因此编译器知道的唯一的事情是包含Object类型的对象。如果那是一个通用的数据结构这会工作。

其他提示

此:

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();
        }
    }
}

按预期方式工作,它给我的IntelliSense显示两者的Bleh和胡说,在Visual Studio 2008。

你有什么的的是,或究竟的是什么?有可能是其他的东西,绊倒智能感知比你表现的代码。

要回答的问题的实际。拼写出类型,并使用var之间唯一的区别是,在某些情况下,你的必须的使用VAR,当你根本就没有正确的类型吧。这一点,如果我没有记错的话,只有相关的,当你使用匿名类型。

有没有其他的差异,并且编译器将选择在左手侧上的相同类型的,因为它有在右手侧。

修改:由于 @Telos 以指出一个不同的是使用时VAR,你当然必须给变量在声明时的值,因为在右手侧的表达式的类型来决定在左边的变量的类型。当拼写出的类型,可以选择当然以不给它的值。

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

有关var的规则非常简单(对于它的工作原理的情况下 - 有各种限制,以阻止你做var x = null;

如果您认为var真的是在做错误的事情,请发表一个简短而完整的程序来演示。

我试图与在控制台应用程序下面的代码来重现此。

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() { }
}

此正常工作,智能感知是正确的,并反射表明j是键入y。我的猜测是,如果你遇到有鬼它更复杂的那么简单的例子在这里。

我使用的Visual Studio 2008 RTM以及

DataTable.Rows返回实现InternalDataCollectionBase,这又实现的ICollection和IEnumerable一个DataRowCollection。代码

foreach(DataRow row in dt.Rows) { }

在DataRowCollection到一个DataRow蒙上每个项目。可以通过改变它来演示此

foreach(int row in dt.Rows) { }

其中编译,但引发InvalidCastException。

如果DataRowCollection实施IEnumerable<DataRow>那么这将不会编译和使用VAR应键入在列表中作为一个DataRow每个对象。

我不相信你已经在你的代码示例提供足够的信息。我做了一个小程序,试图模仿你的行为描述:

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";
}

但是,输出清楚地表明,变量被解决在Y类型,而不是X

您确定您的函数返回一个Ÿ为Y参考,而不是作为一个X参考?

它的工作原理,它应。它把对象类型为“对象”的时候,编译器就无法确定正确的数据类型。

当您使用foreach关键字,则DateRowCollection被虽然IEnumerable接口访问。用于访问的DataRow具体方法是叫做电流和返回一个对象。所以var关键字正在观看当前方法来推断该类型的返回值。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top