C# 通过引用传递索引器访问的泛型集合中对象的成员

C# 通过引用传递索引器访问的泛型集合中对象的成员,c#,generics,collections,C#,Generics,Collections,我已经在C中创建了一个泛型集合的实例,需要通过引用一个方法来传递该集合中结构的一个成员。我可以使用泛型集合的索引器选择要在方法中修改的对象成员吗?我似乎收到一个错误,无法修改“expression”的返回值,因为它不是一个变量,但我得到的与此类似: Deque<Card> deck_of_cards = new Deque<Card>(); // standard deck of 52 playing cards (structs) ModifyRank( ref d

我已经在C中创建了一个泛型集合的实例,需要通过引用一个方法来传递该集合中结构的一个成员。我可以使用泛型集合的索引器选择要在方法中修改的对象成员吗?我似乎收到一个错误,无法修改“expression”的返回值,因为它不是一个变量,但我得到的与此类似:

Deque<Card> deck_of_cards = new Deque<Card>();  // standard deck of 52 playing cards (structs)

ModifyRank( ref deck_of_cards[4].rank, 8);  // Changes the rank (field, int) of the 5th card to 8
我正在转换使用STD::DeQueand Global方法的C++代码,并且我想尽可能多地保留语法。有人知道这个问题的优雅解决方案吗?

没有看到卡片类,我不能确定,但我怀疑卡片的秩属性是属性,而不是字段。换句话说,你有声明

public class Card
{
    public int rank { get; set; }
}
而不是

public class Card
{
    public int rank;
}
但是我的第一个例子中的属性语法实际上是由编译器重写的语法糖

public class Card
{
    private int _rank;

    public int get_rank()
    {
        return rank;
    }

    public int set_rank(int rank)
    {
        _rank = rank;
    }
}
这意味着卡片上的rank属性根本不是int,而是两个方法的包装器。因为rank不是int,所以不能通过引用传递它

现在是优雅的解决方案:

如果ModifyRank方法仅设置其ref参数的值,则可以将第二行代码简化为

deck_of_cards[4].rank = 8;
这对任何读者来说都要清楚得多。如果您的ModifyRank方法正在执行一些特殊的操作,您可以将其添加到某个静态类中:

public static void ModifyRank(this Card c, int newRank)
{
    int rank = c.rank;
    ModifyRank(ref rank, newRank);
    c.rank = rank;
}
这允许您将第二行替换为

deck[4].ModifyRank(8);
没有看到卡片类,我不能确定,但我怀疑卡片的秩属性是一个属性,而不是一个字段。换句话说,你有声明

public class Card
{
    public int rank { get; set; }
}
而不是

public class Card
{
    public int rank;
}
但是我的第一个例子中的属性语法实际上是由编译器重写的语法糖

public class Card
{
    private int _rank;

    public int get_rank()
    {
        return rank;
    }

    public int set_rank(int rank)
    {
        _rank = rank;
    }
}
这意味着卡片上的rank属性根本不是int,而是两个方法的包装器。因为rank不是int,所以不能通过引用传递它

现在是优雅的解决方案:

如果ModifyRank方法仅设置其ref参数的值,则可以将第二行代码简化为

deck_of_cards[4].rank = 8;
这对任何读者来说都要清楚得多。如果您的ModifyRank方法正在执行一些特殊的操作,您可以将其添加到某个静态类中:

public static void ModifyRank(this Card c, int newRank)
{
    int rank = c.rank;
    ModifyRank(ref rank, newRank);
    c.rank = rank;
}
这允许您将第二行替换为

deck[4].ModifyRank(8);

在C中,不鼓励使用ref关键字传递参数。相反,假设卡是一个类,您可能希望更改方法的签名以简单地传递卡:

ModifyRank(deck_of_cards[4], 8); 

由于类在C中,ModifyRank将修改作为参数传递的卡的内容。

在C中不鼓励使用ref关键字传递参数。相反,假设卡是一个类,您可能希望更改方法的签名以简单地传递卡:

ModifyRank(deck_of_cards[4], 8); 

由于类在C中,ModifyRank将修改作为参数传递的卡的内容。

不可能通过引用传递通过索引器获得的结构的字段。要修改此类集合中结构的内容,需要单独的get和set操作,因为索引器不能通过引用返回值(至少在C中不能),这可能与无法验证的MSIL有关

具体问题最直接的解决方案是:

Deque<Card> deck_of_cards = new Deque<Card>();  // standard deck of 52 playing cards
var tmp = deck_of_cards[4];
ModifyRank( ref tmp.rank, 8);  // Changes the rank (int) of the 5th card to 8
deck_of_cards[4] = tmp;

不可能通过引用传递通过索引器获得的结构的字段。要修改此类集合中结构的内容,需要单独的get和set操作,因为索引器不能通过引用返回值(至少在C中不能),这可能与无法验证的MSIL有关

具体问题最直接的解决方案是:

Deque<Card> deck_of_cards = new Deque<Card>();  // standard deck of 52 playing cards
var tmp = deck_of_cards[4];
ModifyRank( ref tmp.rank, 8);  // Changes the rank (int) of the 5th card to 8
deck_of_cards[4] = tmp;

尽管.net泛型集合不能很好地支持使用可变结构,但如果您设计自己的集合,就可以使它们有效地支持可变结构。假设对象类似于EnhancedList,我建议使用如下模式:


使用这种方法,可以将集合的项通过ref传递给任何所需的代码。有点恼人的是,没有办法处理可变泛型,但这种方法允许任意的真正的引用传递语义,只要定义ActionItem变量时有足够的参数。

尽管.net泛型集合不能很好地支持使用可变结构,如果您设计自己的集合,您可以使它们有效地支持可变结构。假设对象类似于EnhancedList,我建议使用如下模式:

使用这种方法,可以将集合的项通过ref传递给任何所需的代码。有点恼人的是,没有办法处理变量泛型,但这种方法允许任意的真正的引用传递语义,只要定义ActionItem变量时有足够的参数。

为什么不编写一副卡[4]。秩=8;?因为actu

我使用的al方法有多个参考参数,在许多地方修改对象比扑克牌复杂得多,这些方法有几种。我希望尽可能保持语法和样式接近C++代码,如果你不告诉我们你想做什么,很难告诉你应该编写什么代码。参数过多的方法可能是设计不良的原因。另外,为什么您希望尽可能靠近旧代码?为什么你甚至转换它?@ USE1130698: C不是C++,与乍一看可能类似。虽然你可能觉得你在C中使用C++风格的构造更安全,但是从长远来看,你会从改写逻辑中获益更多。如果代码是复杂的,那么它可能已经违反了实体OOP原则,即使它是遗留项目。在C++项目中,有一个带有结构的文件、一个具有全局函数的文件、一个具有定义常量的文件,以及一个使用这些文件的类的文件。我将全局函数和常量放在一个静态常量类中,编辑了结构,现在正在修改使用这些函数和常量的类。这些函数使用多个输入和输出执行计算。我希望,这个问题是阻止我在更大的C项目中使用已翻译类的唯一原因。为什么不编写一副卡片[4]。rank=8;?因为我使用的实际方法有多个参考参数,在许多地方修改对象比扑克牌复杂得多,这些方法有几种。我希望尽可能保持语法和样式接近C++代码,如果你不告诉我们你想做什么,很难告诉你应该编写什么代码。参数过多的方法可能是设计不良的原因。另外,为什么您希望尽可能靠近旧代码?为什么你甚至转换它?@ USE1130698: C不是C++,与乍一看可能类似。虽然你可能觉得你在C中使用C++风格的构造更安全,但是从长远来看,你会从改写逻辑中获益更多。如果代码是复杂的,那么它可能已经违反了实体OOP原则,即使它是遗留项目。在C++项目中,有一个带有结构的文件、一个具有全局函数的文件、一个具有定义常量的文件,以及一个使用这些文件的类的文件。我将全局函数和常量放在一个静态常量类中,编辑了结构,现在正在修改使用这些函数和常量的类。这些函数使用多个输入和输出执行计算。我希望,这个问题是唯一阻碍我在更大的C项目中使用已翻译类的原因抱歉,忘了提到Card是一个结构,而不是一个类。同样,该方法更像ModifyInt,并且不仅仅用于Card的级别成员。它必须是一个结构吗?“拥有可变结构是非常不鼓励的,你必须非常小心使用它们。”斯维克同意。正如伟大的圣人埃里克·利珀特所说,可变值类型是邪恶的@user1130698:正如svick提到的,这是在C语言中要避免的另一件事。除了非常小的实体外,通常避免使用结构,这仅仅是出于性能原因。但是,对不起,忘了提到卡是一个结构,而不是一个类。此外,该方法更像ModifyInt,并且不仅仅用于卡的级别成员。它必须是一个结构吗?“拥有可变结构是非常不鼓励的,你必须非常小心使用它们。”斯维克同意。正如伟大的圣人埃里克·利珀特所说,可变值类型是邪恶的@user1130698:正如svick提到的,这是在C语言中要避免的另一件事。除了非常小的实体外,通常避免使用结构,这仅仅是出于性能原因,但是.deck_of_cards[4].rank=8;我不相信这会因为Pent提到的原因而起作用。我验证了成员是字段,而不是属性。我不知道扩展方法。。。谢谢你的点卡[4];我不相信这会因为Pent提到的原因而起作用。我验证了成员是字段,而不是属性。我不知道扩展方法。。。感谢tipI最终使用了这个解决方案;在我的代码中,这个问题的实例并不像我最初想象的那么多。ThanksI最终使用了这个解决方案;在我的代码中,这个问题的实例并不像我最初想象的那么多。谢谢