方括号 [] 在属性中代表什么意思?

3
我正在研究MVC 4 WebGrid的代码,发现它被使用如下:
    grid.Column("Id", format: (item) => item.GetSelectLink(item.Id)),

我不确定"item"参数是什么,所以我查看了源代码,发现它似乎是一个"WebGridRow"类。对我来说问题在于,上面的代码正在寻找一个".Id"属性,但该类中不存在该属性。唯一与其相近的属性看起来像是下面这样:

public object this[string name]
        {
            get
            {
                if (String.IsNullOrEmpty(name))
                {
                    throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "name");
                }
                object value = null;
                if (!TryGetMember(name, out value))
                {
                    throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
                                                                      HelpersResources.WebGrid_ColumnNotFound, name));
                }
                return value;
            }
        }

我从来没有见过像“this[string name]”这样定义的属性,它是什么意思?是动态属性吗?

我试图在网上搜索,但不确定应该搜索什么,我找不到任何结果/解释。

请帮忙解答,谢谢。


5
这是微软官方文档中的链接,讨论了在Visual Studio中使用"CWnd"类的方法。该类提供了一个框架来创建和管理窗口,并且该文档解释了如何使用该类及其成员函数。涉及的主题包括窗口样式、创建和销毁窗口、消息处理等。 - Robert Rouhani
哇,太棒了。非常感谢@RobertRouhani。我简直不敢相信我以前从未听说过这个。看起来非常基础!非常感谢!源代码有点篡改了使用方式。他们用它从WebGridRow的数据源对象中获取属性。真的让我很困惑。 - Liming
4个回答

6

我认为你可能理解不了这里有两个要点(或者我没有理解你的问题)。

this[..] 属性是索引属性。它们就像数组表达式一样使用。例如,你可以想象像这样创建自己的“数组”:

public class MyArray {
     string[] _storrage = new string[100];
     public string this[int index] {
         get { return _storrage[index]; }
         set { _storrage[index] = value; }
     }
}

您也可以创建具有多个参数的索引属性,并且它们可以进行重载。例如,某些列表允许您通过名称(this[string name])和索引(this[int index])访问项目。实际上,这只是语法糖,因此无需像在java中一样编写getItem(int index)方法。
另一个概念似乎是您理解不了的(尽管从您的问题中看不出来)是lambda方法。在您的代码中:
(item) => item.GetSelectLink(item.Id)

是一个 Lambda 方法。例如,如果您的 grid 对象上的方法 Colum 具有以下签名:

public void Column<T>(string name, Func<T, string>)

表达式 (item) => item.GetSelectLink(item.Id) 将评估为一个接受 T 并返回字符串的方法。创建相同功能的另一种方法是这样做:

// in class
public string GetIdField(YourClassType item) { return item.GetSelectLink(item.Id); }

// in Column-call
grid.Column("Id", format: GetIdField);

你可以在这里阅读有关lambda的更多信息:http://msdn.microsoft.com/en-us/library/vstudio/bb397687.aspx [编辑]
为了快速展示一个lambda的例子,可能会使其更加清晰:
var list = new List<string>() { "a", "b", "c" };
list.ForEach((item) => Console.WriteLine(item));

这将输出 "a"、"b" 和 "c"(在 http://ideone.com/MGZxfr 上可以看到运行结果)。 不使用 Lambda 表达式的等效代码应该如下:

void Main() {
    var list = new List<string>() { "a", "b", "c" };
    foreach(var item in list) Print(item);
}

void Print(string item) { Console.WriteLine(item); }

@感谢Alxander。是的,我的意思是我不确定“item”的具体类型是什么,所以我深入源代码中发现它是“WebGridRow”类。同时,感谢您指出这是一个“索引器”。尽管如此,Webgrid的源代码却以完全不同的方式使用它(从对象中获取属性)。 - Liming
@Liming item不是索引器。这就是为什么我认为你混淆了两个概念。item是lambda的方法参数。 - Alxandr
@Liming,请看我的新样例。 - Alxandr
@Alexander,再次感谢您的解释。让我困惑的是“item.Id”。在这种情况下,“YourClassType”是一个“WebGridRow”类,但它没有一个“.Id”属性?那么“item.Id”是什么?请参见此处的源代码:https://github.com/mono/aspnetwebstack/blob/master/src/System.Web.Helpers/WebGrid/WebGridRow.cs - Liming
@Liming 看起来(如果 item 确实是 WebGridRow),它是一个动态对象(这也解释了为什么您在源代码中找不到“.Id”属性)。此外,这也解释了我误解您的问题的原因。您写道“我不确定“item”参数是什么”,所以我认为您不理解 lambda 语法 :) - Alxandr
是的,抱歉,我的意思是感谢指出“this[string name]”是一个索引器。起初,我以为“item.id”与“this[string name]”有些映射关系,因为我不知道索引器是什么。不过Lambda表达式的解释很好,再次非常感谢。看来我现在要学习动态对象了。 - Liming

3

这实际上不是一个属性,而是一个[]操作符。
当您执行类似于以下方式的操作时,将调用get方法:

var a = Ob["hello"]

所谓set

ob["hello"] = 5

3

它是一个索引器MSDN可以帮助你了解更多。


谢谢@juhan_h。是的,我刚发现它是一个索引器。今天又学到了一些东西! - Liming

1

@感谢Recipe。是的,我发现它是一个索引器。每天都学到新东西 :) - Liming
没问题。这就是软件开发的好处;-) - Recipe

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