2010-06-06 3 views
11

가능한 중복 :
How do I assign by “reference” to a class field in c#?C#에서 정수에 대한 참조를 저장하는 방법은 무엇입니까?

안녕하십니까 - 어떻게이 일을 말해? 기본적으로 정수형 참조 형식이 필요합니다 (int *는 C++에서 작동합니다)

class Bar 
{ 
    private ref int m_ref;  // This doesn't exist 

    public A(ref int val) 
    { 
     m_ref = val; 
    } 

    public void AddOne() 
    { 
     m_ref++; 
    } 
} 

class Program 
{ 
    static void main() 
    { 
     int foo = 7; 
     Bar b = new Bar(ref foo); 
     b.AddOne(); 
     Console.WriteLine(foo); // This should print '8' 
    } 
} 

나는 복싱을 사용해야합니까?

편집 : 아마도 더 구체적이어야합니다. BitAccessor 클래스를 작성 중이므로 개별 비트에 액세스 할 수 있습니다. 여기에 내 원하는 사용이다 :

class MyGlorifiedInt 
{ 
    private int m_val; 
    ... 
    public BitAccessor Bits { 
     return new BitAccessor(m_val); 
    } 
} 

사용법 :

BitAccessor이 m_val을 수정할 수 있으려면
MyGlorifiedInt val = new MyGlorifiedInt(7); 
val.Bits[0] = false;  // Bits gets a new BitAccessor 
Console.WriteLine(val); // outputs 6 

, 그것에 대한 참조를 필요로한다. 그러나 원하는 정수에 대한 참조만으로이 BitAccessor를 여러 곳에서 사용하고 싶습니다.

+1

여기에 당신의 목표는 무엇입니까? 이것은 기본적으로 관리되는 코드의 전체 개념에 위배됩니다. 다른 클래스에'foo'에 대한 참조를 저장할 수 있다면'main'과 연결되지 않은 다른 클래스에서'main'이 종료되고'foo'가 살고있는 스택 프레임이 파괴되면 어떻게 될까요? – tzaman

+0

@ tzaman, 제 편집이 제 의도를 분명히 했습니까? @abatishchev - 나는하고 싶습니다만, 대답 중 어느 것도 제가 찾고있는 것을하지 않습니다. 아마 불가능합니다. –

+0

왜 안전하지 않은 포인터로 원하는 것을 할 수 있습니까? C++에서 포인터가 트릭을 수행한다고 언급 한 경우조차도 말입니다. –

답변

6

정수와 같은 정수를 직접 저장할 수는 없지만 수는에 대한 참조를 포함하는 GlorifiedInt 개체에 대한 참조를 저장할 수 있습니다. 귀하의 경우, 내가 할 수있는 일은 BitAccessor 클래스를 GlorifiedInt에 중첩시켜 (개인 필드에 액세스 할 수 있도록) this에 대한 참조를 전달한 다음 m_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); 
      } 
    } 
    } 
} 
+0

고마워요! 이것이 제가 찾고 있던 것입니다. 그리고 BitAccessor는 내가 작성한 것과 동일하게 보입니다. 좋은 점은 더 좋을 것입니다. Integer에 적용 할 수는 있지만 참조 없이는 수행 할 수 없습니다. 그러나 귀하의 솔루션은 내 프로젝트의 범위에서 잘 작동합니다. –

+0

또한이를 추가 할 수 있습니다 : 공공 정적 암시 적 연산자 GlorifiedInt (INT의 V)를 {새로운 GlorifiedInt을 반환 (V); } 예를 들어 다음과 같이 쓸 수 있습니다. GlorifiedInt = 10; – Henry

3

정수에 대한 참조가 필요하지 않습니다. 정수를 참조 유형에 넣으면됩니다. 이는 이미 수행 한 것과 거의 같습니다. 그런 다음 클래스 Bar에 적절한 접근을 추가

Console.WriteLine(bar.Value); 

하고 컴파일 오류를합니다 (ref 키워드를 제거)를 제거 :

Console.WriteLine(foo); 

에 : 그냥이 줄을 변경합니다.

다른 방법 참조에 의해 함수에 정수를 전달하는 것입니다 :

static void AddOne(ref int i) 
{ 
    i++; 
} 

static void Main() 
{ 
    int foo = 7; 
    AddOne(ref foo); 
    Console.WriteLine(foo); 
} 

출력 :

8 
+1

이들 중 어느 것도 정확하게 OP가 요구하는 바가 아니며, 'Bar'객체 내부의 'Main'에있는 로컬 'int foo'에 대한 참조를 저장하는 * 방법을 (정확하게 이해한다면) 'Bar' 인스턴스에 대한 _other_ 메소드 호출은'Main'에서'foo'의 값을 변경합니다. 안전하지 않은 코드에 빠지지 않고 실제로 C#에서 가능한지 확실하지 않습니다. – tzaman

+0

@tzaman, 첫 번째 것은 OP가 요청하는 행동입니다. 'main'의'foo' 사용을'bar.Value'로 대체 한 것을 기억하십시오. 그것은 OP가 그가 원하지 않는 것이 제안하는 정말로 단지 수동 권투 다. –

-1

당신은 당신이 안전하지 않은 코드에 반대하는 지정하지 않았기 때문에이 작동합니다 :

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#에서 포인터를 사용한 적이 없지만 제대로 작동합니다. 가능한 부작용이 무엇인지 잘 모르겠습니다.

+10

당신은 이것을 명백하게 금지되어 있습니다. 이런 식으로 스택 포인터에 대한 참조를 절대 저장하지 않아야합니다. 스택 프레임이 사라진 후에 포인터가 살아남 으면 나쁜 일이 일어납니다. 이것이이 패턴이 처음부터 안전한 코드에서 합법적이지 않은 이유입니다! ** 안전하지 않은 코드를 사용하려면 가능한 모든 부작용이 무엇인지 알아야합니다. 그것이 안전하지 않은 이유입니다. ** –

+0

글쎄요, 저는 매일 새로운 것을 배웁니다. 설명 해줘서 고마워. :) –

-1

이 직접 귀하의 질문에 대답하지 않습니다,하지만 당신은뿐만 아니라 System.Collections.BitArray 클래스를 사용할 수 있습니까?당신이 "다시 발명 바퀴"경우

궁금해?

+0

이 시나리오에서 BitArray를 사용하는 방법을 보여주십시오. – devi

관련 문제