views:

84

answers:

5

I would like to pass the reference of a variable into a class, use it and then get it out later.

Something like this:

// Create the comment Screen
string newCommentText = "";
commentsScreen = new CommentEntry(this, ref newCommentText);

commentScreen.ShowDialog();

...

_dataLayer.SaveOffComment(newCommentText);

And then in the comment class:

public partial class CommentEntry : Form
{
    public CommentEntry(Control pControl, ref string commentResult)
    {
        InitializeComponent();
        control = pControl;

        // ***** Need a way for this to store the reference not the value. *****
        _commentResult = commentResult;  
    }


    private string _commentResult;

    private void CommentEntry_Closing(object sender, CancelEventArgs e)
    {
        _commentResult = tbCommentText.Text.Trim();
    }
}

Is there someway that newCommentText can have the value set in _commentResult in the closing method?

NOTE: Clearly it would be easy to just set a variable in my class and access it after the ShowDialog. This example is only a an approximation of my real issue and accessing any variables in the class after ShowDialog is done is not possible.

A: 

Make newComment property of CommentEntry class.

STO
As I said in the note at the end of my question, I cannot acces any variables of the class after ShowDialog
Vaccano
+3  A: 

This will never work with a String as they are immutable and the variable will change to point to a new instance.

You have two basic options. The first is to simply have a getter for the result so it can be accessed when it is needed later. The other option is to have the owner pass in a delegate method that can be called passing in the resulting value. The owner would then receive the value when the CommentEntry is closing.

unholysampler
A delegate is a good solution
Dan Bryant
+2  A: 

You generally can't directly store a 'reference to a reference' in C#, but you could do something like this:

public interface ICommented
{
    string Comment { get; set; }
}

public class MyClass : ICommented
{
    public string Comment { get; set; }
}

public partial class CommentEntry : Form
{
    public CommentEntry(Control pControl, ICommented commented)
    {
        InitializeComponent();
        control = pControl;

        // ***** Need a way for this to store the reference not the value. *****
        _commented = commented;
    }


    private ICommented _commented;

    private void CommentEntry_Closing(object sender, CancelEventArgs e)
    {
        _commented.Comment = tbCommentText.Text.Trim();
    }
}

So now your form can edit the comment of any class that has said it knows how to be commented upon.

Dan Bryant
That worked great! Thanks for the idea.
Vaccano
+2  A: 

As Dan Bryant pointed out, you cannot do that directly. One option is to wrap the reference into a class, but that requires writing a lot of boilerplate code. A simpler option is to use delegate and lambda functions (in C# 3.0) or anonymous delegates (C# 2.0):

string newCommentText = ""; 
// Using lambda that sets the value of (captured) variable
commentsScreen = new CommentEntry(this, newValue => {
  newCommentText = newValue });  
commentScreen.ShowDialog(); 
_dataLayer.SaveOffComment(newCommentText); 

A modified version of the CommentEntry form would look like this:

public partial class CommentEntry : Form { 
  public CommentEntry(Control pControl, Action<string> reportResult) { 
    InitializeComponent(); 
    control = pControl; 
    // Store the delegate in a local field (no problem here)
    _reportResult = reportResult;    
  } 

  private Action<string> _reportResult; 

  private void CommentEntry_Closing(object sender, CancelEventArgs e) { 
    // Invoke the delegate to notify the caller about the value
    _reportResult(tbCommentText.Text.Trim()); 
  } 
} 
Tomas Petricek