2010-07-19 37 views
6

Trong C++ tôi có thể làm điều này:Tôi có thể sử dụng tham chiếu bên trong hàm C# như C++ không?

int flag=0,int1=0,int2=1; 
int &iRef = (flag==0?int1:int2); 
iRef +=1; 

với hiệu quả mà INT1 được tăng lên.

Tôi phải sửa đổi một số mã C# cũ hơn và nó sẽ thực sự hữu ích nếu tôi có thể làm điều gì đó tương tự, nhưng tôi nghĩ ... có thể không. Có ai không?

+0

Cũng thấy điều này: http://stackoverflow.com/questions/4542536/is-it-possible-to-return-a-reference-to-a-variable-in-c/4542706#4542706 – Betamoo

Trả lời

5

Bạn thể làm điều đó - hoặc ít nhất là một cái gì đó rất giống với những gì bạn muốn - nhưng nó có thể là tốt nhất để tìm cách tiếp cận khác. Ví dụ, bạn có thể bọc các số nguyên bên trong một kiểu tham chiếu đơn giản.

Nếu bạn vẫn muốn làm điều đó, xem lớp Ref<T> đăng bởi Eric Lippert here:

sealed class Ref<T> 
{ 
    private readonly Func<T> getter; 
    private readonly Action<T> setter; 
    public Ref(Func<T> getter, Action<T> setter) 
    { 
     this.getter = getter; 
     this.setter = setter; 
    } 
    public T Value { get { return getter(); } set { setter(value); } } 
} 

public class Program 
{ 
    public static void Main() 
    { 
     int flag=0,int1=0,int2=1; 

     Ref<int> iRef = (flag == 0 ? 
      new Ref<int>(() => int1, z => { int1 = z; }) : 
      new Ref<int>(() => int2, z => { int2 = z; })); 

     iRef.Value += 1; 

     Console.WriteLine(int1); 
    } 
} 

Output:

1 
+0

Cám ơn mẹo. Tôi sẽ kiểm tra. – Gio

1

Sợ không. Bạn có thể làm điều đó với unsafe mã và gợi ý như vậy:

int flag=0,int1=0,int2=1; 
    unsafe 
    { 
     int *iRef = (flag==0? &int1:&int2); 
     *iRef +=1; 
    } 

(không nói đó là một ý tưởng tốt hay bất cứ điều gì :))

2

Nếu tất cả bạn cần là để sửa đổi một kiểu giá trị trong vòng một chức năng, sau đó chuyển tham số với từ khóa ref.

int i = 0;

void increment(ref int integer) 
{ 
    integer++; 
} 

increment(ref i); 

+0

Đừng muốn phải chia nhỏ một hàm thành các hàm con chỉ để sử dụng một tham chiếu. dù sao cũng cảm ơn bạn. – Gio

+0

@Gio: Tôi chưa thấy một trường hợp mà chức năng được đặt tên khéo léo không cải thiện khả năng đọc. Nếu tôi phải chọn giải mã 'Ref ' của Mark (ý tưởng thông minh, '+ 1' từ tôi) và một hàm lấy tham số bằng' ref', tôi chắc chắn sẽ thích một hàm. – sbi

1

Không có equivelent trực tiếp trong C#. Có một vài tùy chọn -

Bạn có thể sử dụng unsafe code and pointers as suggested by dkackman.

Một cách khác là sử dụng loại tham chiếu (lớp) giữ giá trị. Đối với exmaple:

// Using something like 
public class Wrapped<T> { 
    public Wrapped(T initial) { 
     this.Value = initial; 
    } 
    public T Value { get; set; } 
} 

// You can do: 
bool flag=false; 
var int1 = new Wrapped<int>(0); 
var int2 = new Wrapped<int>(1); 

Wrapped<int> iRef = flag ? int2 : int1; 

iRef.Value = iRef.Value + 1; 

Vì bạn đang làm việc với các tài liệu tham khảo để một lớp học, sự phân công để iRef bản sao tài liệu tham khảo, và các công trình trên ...

8

UPDATE: Các tính năng thảo luận dưới đây cuối cùng đã được thêm vào trong C# 7.


tính năng nào bạn muốn - để làm cho quản lý bí danh biến địa phương không được hỗ trợ trong C#. Bạn có thể làm điều đó với thông số chính thức - bạn có thể tạo thông số chính thức là bí danh của bất kỳ biến nào - nhưng bạn không thể tạo địa phương là bí danh của bất kỳ biến nào.

Tuy nhiên, không có kỹ thuật khó ngăn chúng tôi làm như vậy; hệ thống kiểu CLR hỗ trợ "các biến cục bộ". (Nó cũng hỗ trợ các kiểu trả về ref nhưng không hỗ trợ các trường ref.)

Một vài năm trước tôi thực sự đã viết một phiên bản nguyên mẫu của C# hỗ trợ người dân địa phương và các kiểu trả về, và nó hoạt động rất tốt. bằng chứng rằng chúng ta có thể làm như vậy thành công. Tuy nhiên, rất khó có khả năng tính năng này sẽ được thêm vào C# bất kỳ lúc nào, nếu có.Xem http://ericlippert.com/2011/06/23/ref-returns-and-ref-locals/ để biết chi tiết.

Tôi lưu ý rằng nếu tôi là bạn, tôi sẽ tránh điều này bằng bất kỳ ngôn ngữ nào. Viết các chương trình trong đó hai biến chia sẻ cùng một bộ nhớ làm cho mã khó đọc, khó hiểu, khó sửa đổi và khó duy trì.

cũng Xem câu hỏi liên quan: Why doesn't C# support the return of references?

+0

Tôi đã thấy thành ngữ này được sử dụng cho các công cụ dòng lệnh hoặc đọc từ một tệp được chuyển thành tham số hoặc stdin: 'std :: istream & is = blah()? ifs: std :: cin'. Tôi sẽ gọi một hàm với 'ifs' hoặc' std :: cin', nhưng một số khác có vẻ không thích hợp với các cuộc gọi hàm bổ sung. – sbi

+0

@sbi: Nhưng trong C# một luồng đã là một kiểu tham chiếu, vì vậy không có vấn đề gì trong C#: Stream s = f? s1: s2 ;, không phải lo lắng. Điều này chỉ trở nên thú vị khi biến là * giá trị loại *, như trong ví dụ của Gio. Không có cách nào để tạo hai * giá trị * các bí danh cục bộ cho nhau trong C# mà không sử dụng các tham số chính thức. –

+1

Tôi hiểu điều đó. Tôi vừa trả lời câu nói của bạn "Viết chương trình trong đó hai biến chia sẻ cùng một bộ nhớ làm cho mã khó đọc, khó hiểu, khó sửa đổi và khó duy trì". Nó không phải luôn luôn như vậy. – sbi

1

Bạn có thể sử dụng một Action delegate như thế này:

int flag = 0, int1 = 0, int2 = 0; 
Action increment = flag == 0 ? (Action) (() => ++int1) :() => ++int2; 
increment(); 
2

Có bạn có thể làm điều đó với C# 7.0. Nó có hỗ trợ cho trở về tài liệu tham khảo và lưu trữ tài liệu tham khảo. Xem câu trả lời của tôi here.

Các vấn đề liên quan