[英]Using a double by reference in C#
假设我有一个监控double值的类。 我不想每次在监视类中调用monitor方法时都传递该double值。 因此,我想在构造函数中传递对double的引用,并将其存储,以便可以直接在monitor方法中比较值。
我的尝试是:
class Monitor {
double v;
public Monitor(ref double x) { v = x; }
public watch() { Console.WriteLine("Value is: " + v); }
}
并将其与:
double d = 10;
Monitor m = new Monitor(ref d);
while (d > 0) {
m.watch();
d--;
}
不幸的是,这不起作用,因为Monitor构造函数中的赋值将值存储在v变量中。 我试图将变量声明为ref double v
但ref只能在方法参数中使用。
在此建议附近是否有不包含装箱/拆箱或在每个watch
电话中传递d
值的解决方案?
谢谢
注意:我要使用它的具体情况与上面的代码无关。 这只是轻松显示我想要实现的目标的一种方式。
简短的答案是您不能存储对double的引用(或与此相关的任何其他值类型)。 引用只能传递给方法(不能在调用之间存储)。
长的答案是,您可以将其包装在这样的类中并传递该类:
class DoubleWrap
{
protected double val;
public DoubleWrap(double _val) { val = _val; }
public double Value { get { return val } set { val = value; } }
}
然后,当您使用它时:
class Monitor {
DoubleWrap v;
public Monitor(DoubleWrap x) { v = x; }
public watch() { Console.WriteLine("Value is: " + v.Value); }
}
请注意,编译器必须进行一些特殊的提升,但是我不确定声明为结构类型的局部变量的内容/方式! (也就是说,我对缺少它的开销没有要求。)
但是,我确实喜欢闭包,并且发现它“不那么侵入”,因此:
class Monitor {
Func<double> v;
public Monitor(Func<double> x) { v = x; }
public watch() { Console.WriteLine("Value is: " + v()); }
}
double d = 10;
Monitor m = new Monitor(() => d);
while (d > 0) {
m.watch();
d--;
}
ref/out
参数 (这不是一般类型的属性) 必须始终引用有效变量(让我们忽略VB.NET的属性窍门),因此这些属性不能应用于外部(成员)变量:
可以在编译时确保“引用有效变量”语义的唯一方法是限制在当前调用框架中使用ref/out
语义-在方法主体中读取:-作为带有“引用变量”保证存在。 出于这个原因, ref/out
甚至不能在嵌套的闭包/代理/ lambda中使用。 它们可能会被从当前调用框架中取消/调用。
由于您正在尝试跟踪变量是否发生更改,因此,与其轮询IMHO的更改,更好的方法是将变量包装在可观察的范围内。 然后,当变量更改时,您可以接收事件。 当然,您必须更改从变量读取和写入的方式。
public class ObservableObject<T>
: INotifyPropertyChanging, INotifyPropertyChanged
{
public ObservableObject(T defaultValue = default(T),
IEqualityComparer<T> comparer = null)
{
this.value = defaultValue;
this.comparer = comparer ?? EqualityComparer<T>.Default;
}
private T value;
private IEqualityComparer<T> comparer;
public T Value
{
get { return value; }
set
{
if (!comparer.Equals(this.value, value))
{
OnValueChanging();
this.value = value;
OnValueChanged();
}
}
}
public event PropertyChangingEventHandler PropertyChanging;
protected virtual void OnValueChanging()
{
var propertyChanging = PropertyChanging;
if (propertyChanging != null)
propertyChanging(this, new PropertyChangingEventArgs("Value"));
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnValueChanged()
{
var propertyChanged = PropertyChanged;
if (propertyChanged != null)
propertyChanged(this, new PropertyChangedEventArgs("Value"));
}
}
然后,您可以执行以下操作:
var d = new ObservableObject<double>(10);
d.PropertyChanged += (o, e) =>
{
var obs = (ObservableObject<double>)o;
Console.WriteLine("Value changed to: {0}", obs.Value);
};
Console.WriteLine("Value is: {0}", d.Value);
d.Value = 20;
Console.WriteLine("Value is: {0}", d.Value);
如果要传递对内在值类型的引用,请制作长度为1的数组。 所有数组都是引用类型。
class A {
private double[] sharedDbl;
public A(double[] d) {
sharedDbl = d;
}
}
class Program {
public static void Main() {
// other code
double[] shared = new double[1];
A a1, a2;
shared[0] = 34.55d;
a1 = new A(shared);
a2 = new A(shared);
// Now both a1 and a2 have a reference to the same double value.
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.