如何在C#中存储对整数的引用?
可能重复:如何在C#中存储对整数的引用?,c#,reference,value-type,C#,Reference,Value Type,可能重复: 大家好,告诉我怎么做?基本上,我需要一个整数引用类型(int*可以在C++中使用) 我必须使用拳击吗 编辑: 也许我应该说得更具体些。我正在编写一个BitAccessor类,它只允许访问单个位。以下是我想要的用法: class MyGlorifiedInt { private int m_val; ... public BitAccessor Bits { return new BitAccessor(m_val); } } 用法: MyGlo
大家好,告诉我怎么做?基本上,我需要一个整数引用类型(int*可以在C++中使用) 我必须使用拳击吗 编辑: 也许我应该说得更具体些。我正在编写一个BitAccessor类,它只允许访问单个位。以下是我想要的用法:
class MyGlorifiedInt
{
private int m_val;
...
public BitAccessor Bits {
return new BitAccessor(m_val);
}
}
用法:
MyGlorifiedInt val = new MyGlorifiedInt(7);
val.Bits[0] = false; // Bits gets a new BitAccessor
Console.WriteLine(val); // outputs 6
为了使BitAccessor能够修改m_val,它需要一个对它的引用。但是我想在很多地方使用这个位访问器,只引用所需的整数。您不需要引用整数-只需将整数放入引用类型中-这几乎是您已经做过的。只需更改这一行:
Console.WriteLine(foo);
致:
然后向类栏
添加适当的访问器,并删除编译错误(删除ref
关键字)
另一种方法是通过引用将整数传递给函数:
static void AddOne(ref int i)
{
i++;
}
static void Main()
{
int foo = 7;
AddOne(ref foo);
Console.WriteLine(foo);
}
输出:
8
您没有指定您反对不安全代码,因此这应该可以:
unsafe class Bar {
private int* m_ref;
public Bar(int* val) {
m_ref = val;
}
public void AddOne() {
*m_ref += 1;
}
}
unsafe class Program {
static void Main() {
int foo = 7;
Bar b = new Bar(&foo);
b.AddOne();
Console.WriteLine(foo); // prints 8
Console.ReadLine();
}
}
我从未在C#中使用过指针,但它似乎可以工作。我只是不确定可能的副作用是什么。不能直接存储对那样的整数的引用,但可以存储对包含它的
GlorifiedInt
对象的引用。在您的情况下,我可能要做的是将BitAccessor
类嵌套在GlorifiedInt
中(这样它就可以访问私有字段),然后在创建时将对this
的引用传递给它,然后它就可以使用它访问mu val
字段。下面是一个例子,它可以满足您的需求:
class Program
{
static void Main(string[] args)
{
var g = new GlorifiedInt(7);
g.Bits[0] = false;
Console.WriteLine(g.Value); // prints "6"
}
}
class GlorifiedInt
{
private int m_val;
public GlorifiedInt(int value)
{
m_val = value;
}
public int Value
{
get { return m_val; }
}
public BitAccessor Bits
{
get { return new BitAccessor(this); }
}
public class BitAccessor
{
private GlorifiedInt gi;
public BitAccessor(GlorifiedInt glorified)
{
gi = glorified;
}
public bool this[int index]
{
get
{
if (index < 0 || index > 31)
throw new IndexOutOfRangeException("BitAcessor");
return (1 & (gi.m_val >> index)) == 1;
}
set
{
if (index < 0 || index > 31)
throw new IndexOutOfRangeException("BitAcessor");
if (value)
gi.m_val |= 1 << index;
else
gi.m_val &= ~(1 << index);
}
}
}
}
类程序
{
静态void Main(字符串[]参数)
{
var g=新的荣耀力(7);
g、 位[0]=假;
Console.WriteLine(g.Value);//打印“6”
}
}
等级荣誉力
{
私人国际博物馆;
公共荣誉力(int值)
{
m_val=值;
}
公共整数值
{
获取{return m_val;}
}
公共位存取器位
{
获取{返回新的位访问器(this);}
}
公共类位存取器
{
私人格洛里菲丁gi;
公共比特存取器(美化)
{
gi=荣耀;
}
公共bool此[int索引]
{
得到
{
如果(指数<0 | |指数>31)
抛出新的IndexOutOfRangeException(“BitAcessor”);
返回值(1&(gi.m_val>>索引))==1;
}
设置
{
如果(指数<0 | |指数>31)
抛出新的IndexOutOfRangeException(“BitAcessor”);
如果(值)
gi.m|val |=1这并不能直接回答你的问题,但你能不能不使用这个类
只是想知道你是否在“重新发明轮子”这两个都不是OP想要的,这似乎是(如果我理解正确的话)将引用存储到Bar
对象内部Main
中的本地int foo
的某种方法,以便其他方法调用Bar
实例来更改Main
中foo
的值。不确定这在C#中是否实际可行,而不进入不安全的代码…@tzaman,第一个方法是P是在请求,从行为角度来看;记住我们已经用bar.Value
取代了Main
对foo
的使用。不过,实际上这只是手动装箱,OP建议他不要。你的目标是什么?这基本上违背了托管代码的整体理念;如果你可以在som中存储对foo
的引用另一个生命周期与main
没有关联的类,当main
退出并且foo
所在的堆栈框架被破坏时会发生什么?@tzaman,我的编辑是否澄清了我的意图?@abatishchev-我很想,但这两个答案都不是我想要的。也许这不可能。为什么不可能呢指针是你想做的吗?你甚至提到指针会在C++中做这个技巧。这是一个重复的例子,我在这里解释了为什么你不能把一个参考值存储到一个字段中的变量,以及如何绕过这个限制。是的,我想我现在明白了你想做的事情。ust that。明确禁止您这样做。您决不能像这样存储对堆栈指针的引用。如果堆栈帧消失后指针仍然存在,则会发生不好的事情。这就是为什么此模式在安全代码中首先是不合法的!不安全代码要求您知道所有可能的副作用;这就是为什么它是安全的这是不安全的。我每天都会学到一些新的东西。谢谢你的解释。:)谢谢你!这就是我一直在寻找的。你的BitAccessor看起来和我写的完全一样。唯一更好的办法就是能够将它应用到任何整数上——但是没有参考就无法做到。你的解决方案对于但是,我的项目的范围。您也可以添加以下内容:公共静态隐式运算符GlorifiedInt(int v){return new GlorifiedInt(v);}这允许您编写,例如GlorifiedInt a=10;请说明如何在此场景中使用位数组
unsafe class Bar {
private int* m_ref;
public Bar(int* val) {
m_ref = val;
}
public void AddOne() {
*m_ref += 1;
}
}
unsafe class Program {
static void Main() {
int foo = 7;
Bar b = new Bar(&foo);
b.AddOne();
Console.WriteLine(foo); // prints 8
Console.ReadLine();
}
}
class Program
{
static void Main(string[] args)
{
var g = new GlorifiedInt(7);
g.Bits[0] = false;
Console.WriteLine(g.Value); // prints "6"
}
}
class GlorifiedInt
{
private int m_val;
public GlorifiedInt(int value)
{
m_val = value;
}
public int Value
{
get { return m_val; }
}
public BitAccessor Bits
{
get { return new BitAccessor(this); }
}
public class BitAccessor
{
private GlorifiedInt gi;
public BitAccessor(GlorifiedInt glorified)
{
gi = glorified;
}
public bool this[int index]
{
get
{
if (index < 0 || index > 31)
throw new IndexOutOfRangeException("BitAcessor");
return (1 & (gi.m_val >> index)) == 1;
}
set
{
if (index < 0 || index > 31)
throw new IndexOutOfRangeException("BitAcessor");
if (value)
gi.m_val |= 1 << index;
else
gi.m_val &= ~(1 << index);
}
}
}
}