Yes, that code will work, but it needs explanation, because there is a whole world of code that will not work, and you're likely to trip into that unless you know this.
Before I forget: Mutable structs are evil. OK, with that out of the way, let's move on.
Let's take a simple example, you can use LINQPad to verify this code:
void Main()
{
var s = new MyStruct();
Test(s);
Debug.WriteLine(s.Description);
}
public void Test(IMyInterface i)
{
i.Description = "Test";
}
public interface IMyInterface
{
string Description { get; set; }
}
public struct MyStruct : IMyInterface
{
public string Description { get; set; }
}
When executing this, what will be printed?
null
OK, so why?
Well, the problem is this line:
Test(s);
This will in fact box that struct and pass the boxed copy to the method. You're successfully modifying that boxed copy, but not the original s
variable, which was never assigned anything, and is thus still null
.
OK, so if we change just one line in the first piece of code:
IMyInterface s = new MyStruct();
Does this change the outcome?
Yes, because now you're boxing that struct here, and always use the boxed copy. In this context it behaves like an object, you're modifying the boxed copy and writing out the contents of the boxed copy.
The problem thus crops up whenever you box or unbox that struct, then you get copies that live separate lives.
Conclusion: Mutable structs are evil.
I see two answers about using ref
here now, and this is barking up the wrong tree. Using ref
means you've solved the problem before you added ref
.
Here's an example.
If we change the Test
method above to take a ref
parameter:
public void Test(ref IMyInterface i)
Would this change anything?
No, because this code is now invalid:
var s = new MyStruct();
Test(ref s);
You'll get this:
The best overloaded method match for 'UserQuery.Test(ref UserQuery.IMyInterface)' has some invalid arguments
Argument 1: cannot convert from 'ref UserQuery.MyStruct' to 'ref UserQuery.IMyInterface'
And so you change the code to this:
IMyInterface s = new MyStruct();
Test(ref s);
But now you're back to my example, just having added ref
, which I showed is not necessary for the change to propagate back.
So using ref
is orthogonal, it solves different problems, but not this one.
OK, more comments regarding ref
.
Yes, of course passing a struct around using ref
will indeed make the changes flow throughout the program.
That is not what this question was about. The question posted some code, asked if it would work, and it would. In this particular variant of code it would work. But it's so easy to trip up. And pay particular note that the question was regarding structs and interfaces. If you leave interfaces out of it, and pass the struct around using ref
, then what do you have? A different question.
Adding ref
does not change this question, nor the answer.