简体   繁体   English

为什么遵循静态函数不起作用?

[英]Why following static function doesn't work ?

Here is my code : 这是我的代码:

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

Later In my code I do : 稍后在我的代码中,我这样做:

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

How to fix this ? 如何解决呢?

None of the answers given so far are actual explanations. 到目前为止,给出的答案都不是实际的解释。

A number of the answers given so far state that this happens because int is a value type. 到目前为止,给出的许多答案都表明发生这种情况是因为int是一种值类型。 Try replacing all the int s with object s in this program. 尝试在此程序中将所有int替换为object Does it start working the way the original poster expects? 它会按照原始海报的预期开始工作吗? No. Then it has nothing to do with value types vs reference types. 否。那么它与值类型与引用类型无关。

Rather, it has to do with the value of a variable , regardless of its type. 相反,它与变量的值有关,而与变量的类型无关。

Mahdi, your expectation is that formal parameter j becomes an alias for formal parameter i , which is in turn an alias for local variable g , and that therefore any change to j also causes a change to g because they are the same variable. Mahdi,您的期望是形式参数j成为形式参数i别名 ,而形式参数i又是局部变量g的别名,因此对j任何更改也将导致对g的更改,因为它们是相同的变量。 That's not the case. 事实并非如此。 j , i and g are copies of the same value but have different storage locations , so mutating one does not mutate the other. jig相同值的副本,但具有不同的存储位置 ,因此,使一个变量不变就不会使另一个变量突变。

The way you say "this formal parameter is an alias for this variable" in C# is by using the ref or out keywords. 在C#中,您说“此形式参数是此变量的别名”的方式是使用refout关键字。 So this program would do what you expect: 因此,该程序可以实现您的期望:

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

The "ref" keywords mean that g , i , and j are all different names for the same variable. “ ref”关键字表示gij都是同一变量的不同名称。

As D Stanley notes, this is probably bad style. 正如D Stanley所指出的那样,这可能是不好的风格。 Rather than mutating a variable in a method, instead return the value you want it to be changed to, and let the caller decide what variable to mutate, if any. 与其更改方法中的变量,不如返回您想要将其更改为的值,并让调用者确定要更改的变量(如果有)。

Your code path doesn't change as a result of calling the Action , so the program always returns i . 调用Action不会导致代码路径更改,因此程序始终返回i

It looks like you expect g to be changed to 11 after the first call, which is not true since the value of g is copied to j and then to i rather than a reference to g , meaning the value at g is not modified as a result of your action. 它看起来像你期望g第一个电话,因为G的复制到这是不正确后改为11 j ,然后到i ,而不是参考 g ,意在值g没有被修改为您的行动的结果。

One option would be to return the value instead of trying to modify it: 一种选择是返回值,而不是尝试修改它:

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 */ 

您的代码返回被调用的整数,因此两种情况均返回g ,即22

You're trying to alter the value of g through the Action<int> act , right? 您正在尝试通过Action<int> act改变g的值,对吗?

It won't work as the integer is a primitive type which is passed as value, not as reference, so you're not in fact assigning any value to g. 由于整数是作为值而不是引用传递的原始类型,因此它将不起作用,因此实际上您没有为g分配任何值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM