Reputation: 10650
As in the title.
I know this is possible in other languages - is it in C#?
If the question title isn't clear, i would like something that does (something like) this:
MyClass exampleObject1 = new MyClass(...)
exampleObject1.sort() //sort method detects that value is not being assigned and performs sort in place.
MyClass exampleObject2 = exampleObject1.sort() //method detects assignment and returns new sorted object leaving original untouched.
is this something that's possible without resorting to magic? If it is possible, but in some nasty way, what is that way?
EDIT: for those wanting to see an example where you can do this (in python): here. Note that i caveat it with the issue that it does not always work - but this is only in relation to the way i did it when i answered the question. Now i know more about inspect, and you can get all the information you need from the stack to work out if it is being assigned anywhere or not.
Upvotes: 1
Views: 238
Reputation: 718
Split the Copy and Sort methods into two distinct methods. If I want to sort a copy, I should be responsible for copying before I sort. For example:
var copy = myCollection.Copy();
copy.Sort();
The goal should be making it clear what your function is doing to any calling code. Different behavior based on usage is only going to lead to bugs, at least in the C# world.
Upvotes: 0
Reputation: 3047
Of course, you definitely shouldn't be doing this, but since the OP is more interested if it could be done for curiosity sake, then here is a snippet of code that demonstrates this capability:
class SomeWeirdClass
{
private bool sortApplied = false;
private List<int> elements;
public IList<int> Elements
{
get
{
if(sortApplied)
{
elements.Sort();
sortApplied = false;
}
return elements;
}
}
public SomeWeirdClass(IEnumerable<int> elements)
{
this.elements = elements.ToList();
}
public SortedWeirdClass Sort()
{
sortApplied = true;
return new SortedWeirdClass(this);
}
public class SortedWeirdClass
{
SomeWeirdClass parent;
internal SortedWeirdClass(SomeWeirdClass parent)
{
this.parent = parent;
}
public static implicit operator SomeWeirdClass(SortedWeirdClass sorted)
{
sorted.parent.sortApplied = false;
var elementCopy = new int[sorted.parent.elements.Count];
sorted.parent.elements.CopyTo(elementCopy);
var result = new SomeWeirdClass(elementCopy);
result.Sort();
return result;
}
}
}
Now using it in a program:
static void Main(string[] args)
{
SomeWeirdClass original = new SomeWeirdClass(new[] { 5, 1, 4, 3, 2 });
Console.WriteLine("Original Data: ");
Console.WriteLine(string.Join(" ", original.Elements));
SomeWeirdClass copy = original.Sort();
Console.WriteLine("Original Data after Sort and Assignment: ");
Console.WriteLine(string.Join(" ", original.Elements));
Console.WriteLine("Sorted Copy:");
Console.WriteLine(string.Join(" ", copy.Elements));
original.Sort();
Console.WriteLine("Original Data after Sort without Assignment: ");
Console.WriteLine(string.Join(" ", original.Elements));
}
The program outputs:
Original Data:
5 1 4 3 2
Original Data after Sort and Assignment:
5 1 4 3 2
Sorted Copy:
1 2 3 4 5
Original Data after Sort without Assignment:
1 2 3 4 5
The hack here is that sorting actually creates a temporary class which wraps the original. Unless that result is implicitly cast to the original type via assignment, the sorting effects will be applied to the original dataset. If assignment is made, the sorting is cancelled, and a copy is made for the new variable.
Upvotes: 5
Reputation: 23324
It is not possible in a reliable way. The compiler can optimize
MyClass exampleObject2 = exampleObject1.sort();
to exampleObject1.sort();
if exampleObject2
is not used.
To answer a slightly different question: you could return a Lazy<MyClass>
. So you can do the sort only if the result is actually used.
Upvotes: 0