0

这是我的代码:

public static class s {

    public static int Dx(this int i, Action<int> act, Func<int, bool> con) {
        if (con(i)) act(i);
        return i;
    }
}

稍后在我的代码中,我这样做:

int g = 22;
int false_con = g.Dx(j => j = 11, z => z != 22); // This is 22 which is fine.
int true_con = g.Dx(j => j = 11, z => z == 22);  //This is also 22 which should be 11

如何解决这个问题?

4

4 回答 4

16

到目前为止给出的答案都不是实际的解释。

到目前为止给出的许多答案都表明发生这种情况是因为 int 是一种值类型。尝试在此程序中将所有ints替换为 s。object它是否开始按照原始海报所期望的方式工作?不,那么它与值类型与引用类型无关。

相反,它与变量的值有关,无论其类型如何。

Mahdi,您的期望是形式参数j成为形式参数的别名,而形式参数i又是局部变量的别名g,因此任何更改j都会导致更改,g因为它们是相同的变量。事实并非如此。ji并且g相同值的副本,但具有不同的存储位置,因此改变一个不会改变另一个。

您在 C# 中说“此形式参数是此变量的别名”的方式是使用reforout关键字。所以这个程序会做你所期望的:

delegate void RefAction<T>(ref T t);
...
public static int Dx(ref int i, RefAction<int> act, Func<int, bool> con) 
{
    if (con(i)) 
        act(ref i);
    return i;
}
...
int g = 22;
int false_con = Dx(ref g, (ref int j) => { j = 11; }, z => z != 22); 
int true_con = Dx(ref g, (ref int j) => { j = 11; }, z => z == 22); 

“ref”关键字意味着gij都是同一变量的不同名称。

正如 D Stanley 所说,这可能是一种糟糕的风格。与其在方法中更改变量,不如返回您希望将其更改为的值,并让调用者决定要更改的变量(如果有)。

于 2013-04-04T14:58:18.753 回答
3

您的代码路径不会因调用 而改变Action,因此程序总是返回i.

看起来您希望g在第一次调用后更改为 11,这是不正确的,因为g的j被复制到然后复制到i而不是对 的引用g这意味着 at 的值g不会因为您的操作而被修改。

一种选择是返回值而不是尝试修改它:

public static int Dx(this int i, Func<int, int> act, Func<int, bool> con) {
    if (con(i)) return act(i);
    return i;
}

int g = 22;
g = g.Dx(j => 11, z => z != 22); /* g is still 22 */ 
g = g.Dx(j => 11, z => z == 22);  /* g is now 11 */ 
于 2013-04-04T13:24:28.933 回答
1

您的代码返回调用它的整数,因此两种情况都返回gwhich is 22

于 2013-04-04T13:24:15.400 回答
0

您正试图通过 更改 的值gAction<int> act对吗?

它不起作用,因为整数是作为值传递的原始类型,而不是作为引用传递,所以你实际上并没有为 g 分配任何值。

于 2013-04-04T13:25:42.453 回答