Impossible to use ref and out for first ( this ) parameter in Extension methods?
You have to specify ref
and out
explicitly. How would you do this with an extension method? Moreover, would you really want to?
TestClass x = new TestClass();
(ref x).ChangeWithExtensionMethod(otherTestClass);
// And now x has changed?
Or would you want to not have to specify the ref
part, just for the first parameter in extension methods?
It just sounds weird to me, to be honest, and a recipe for unreadable (or at least hard-to-predict) code.
Using ref or out in a extension
List.Clear()
isn't an extension method, it's a method. And even if it was an extension method, it wouldn't need to receive the parameter as ref
, because it doesn't "return" a different list than the one you had, it modifies the list.
And, in general, you can't. But you normally don't need to.
What about:
public static bool Invert(this bool value)
{
return !value;
}
bool x = false.Invert();
C#. Ref returning delegate for ref extension method
A ref
parameter is something you can only use within your function, not something you can "save for later". That's because the ref
parameter cannot keep its referent variable alive.
Consider using a reference type (C# parlance: class
) to hold your data. Then you can have any number of handles to it, and they'll participate in garbage collection (object lifetime, memory compaction, etc). Unfortunately, this requires changing all users of the variable -- it's not something you can retrofit onto data in an existing object model.
Doesn't C# Extension Methods allow passing parameters by reference?
No. In C#, you cannot specify any modifiers (like 'out' or ref
) other than this
for the first parameter of an extension method - you can for the others. Not familiar with the VB Syntax but it seems to be using a declarative approach to mark an extension method.
When you call it, you do not specify the first this
parameter. Hence marking the parameter as out or ref doesnt make sense as You can't specify the modifier when you call it like you'd do for normal methods
void MyInstanceMethod(ref SomeClass c, int data) { ... } // definition
obj.MyInstanceMethod(ref someClassObj, 10); // call
void MyExtensionMethod(this SomeClass c, int data) {.... } // defn
c.MyExtensionMethod(10); // call
I think the trouble you're having here is related to value types being immutable. If Weekdays was a reference type, it would work out alright. For immutable types (structs), the defacto way is to return a new instance with the required value. E.g. See the Add method on the struct DateTime, it returns a new DateTime instance whose value = receiver DateTime instance's value + param value.
public DateTime Add( TimeSpan value )
Extension method with ref does not work with arrays
ref
must be specified both in the method declaration and when it is called.
If the this
argument of the extension could be passed by reference, there wouldn't be any way to specify it when calling the method.
someObject.CallSomeExtensionMethod();
Where would we put ref
? There is nowhere.
If we could pass a value by reference without knowing that we're passing it by reference, weird things could happen. It's normal to call an extension method that modifies the value passed as the first argument. For example, we could write an extension method to shuffle a list:
list.Shuffle();
We expect the list to be modified. But imagine our surprise if the extension method actually caused list
to point to an entirely different instance of List
. Even if we knew it was happening that would be weird, but if that behavior wasn't explicit it would be chaos. We could call an extension that isn't ref
and someone could change it to be ref
without breaking anything, introducing all sorts of crazy, unpredictable effects.
Having ref
in both the method and where it's used is like a contract - that method is telling us that it may replace our reference, and we're giving it explicit permission.
C# out parameter in extension method
Extension methods can have out parameters. You need to specify the type of your out parameter. So change code
public static int customMax(this int[] data, out index)
to
public static int customMax(this int[] data, out int index)
and it should all work
Passing array by reference to extension methods
You can't send extension's target object by ref.
Do you relly need it?
Is array replaced by the new one by the extension method?
Generic Extension Method for change value of any variable or object
What you want is impossible, as an extension-method allways works on a specific instance of a type. As every other method as well, a method can not change the instance to be something different (which would mean reference another instance), it can only modify that instance by calling any of its members.
If you want to know why it is forbidden to use ref
on an extension-method, look this similar question: Impossible to use ref and out for first ("this") parameter in Extension methods?.
On the other hand you can do that with normal methods using the ref
-keyword, though.
public static void Set<T>(ref T instance)
{
instance = new Whatever(...);
}
Now you may be able to use this:
var n = 0;
TheClass.Set(ref n);
However if all you want to do in that method is replacing one reference by another one, why not just use this instead?
var n = 0;
n = 1;
Identify if a string is a number
int n;
bool isNumeric = int.TryParse("123", out n);
Update As of C# 7:
var isNumeric = int.TryParse("123", out int n);
or if you don't need the number you can discard the out parameter
var isNumeric = int.TryParse("123", out _);
The var s can be replaced by their respective types!
Task.Run with Parameter(s)?
private void RunAsync()
{
//Beware of closures. String is immutable.
string param = "Hi";
Task.Run(() => MethodWithParameter(param));
}
private void MethodWithParameter(string param)
{
//Do stuff
}
Edit
Due to popular demand I must note that the Task
launched will run in parallel with the calling thread. Assuming the default TaskScheduler
this will use the .NET ThreadPool
. Anyways, this means you need to account for whatever parameter(s) being passed to the Task
as potentially being accessed by multiple threads at once, making them shared state. This includes accessing them on the calling thread.
In my above code that case is made entirely moot. Strings are immutable. That's why I used them as an example. But say you're not using a String
...
One solution is to use async
and await
. This, by default, will capture the SynchronizationContext
of the calling thread and will create a continuation for the rest of the method after the call to await
and attach it to the created Task
. If this method is running on the WinForms GUI thread it will be of type WindowsFormsSynchronizationContext
.
The continuation will run after being posted back to the captured SynchronizationContext
- again only by default. So you'll be back on the thread you started with after the await
call. You can change this in a variety of ways, notably using ConfigureAwait
. In short, the rest of that method will not continue until after the Task
has completed on another thread. But the calling thread will continue to run in parallel, just not the rest of the method.
This waiting to complete running the rest of the method may or may not be desirable. If nothing in that method later accesses the parameters passed to the Task
you may not want to use await
at all.
Or maybe you use those parameters much later on in the method. No reason to await
immediately as you could continue safely doing work. Remember, you can store the Task
returned in a variable and await
on it later - even in the same method. For instance, once you need to access the passed parameters safely after doing a bunch some other work. Again, you do not need to await
on the Task
right when you run it.
Anyways, a simple way to make this thread-safe with respect to the parameters passed to Task.Run
is to do this:
You must first decorate RunAsync
with async
:
private async void RunAsync()
Important Notes
Preferably the method marked async
should not return void, as the linked documentation mentions. The common exception to this is event handlers such as button clicks and such. They must return void. Otherwise I always try to return a Task
or Task<TResult>
when using async
. It's good practice for a quite a few reasons.
Now you can await
running the Task
like below. You cannot use await
without async
.
await Task.Run(() => MethodWithParameter(param));
//Code here and below in the same method will not run until AFTER the above task has completed in one fashion or another
So, in general, if you await
the task you can avoid treating passed in parameters as a potentially shared resource with all the pitfalls of modifying something from multiple threads at once. Also, beware of closures. I won't cover those in depth but the linked article does a great job of it.
Regarding Run
and StartNew
the code below I find most important to know, really. There are legitimate reasons to use either, neither is obsolete or "better" than the other. Be aware simply replacing one with the other is a very bad idea unless you understand this:
//These are exactly the same
Task.Run(x);
Task.Factory.StartNew(x, CancellationToken.None,
TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
//These are also exactly the same
Task.Factory.StartNew(x);
Task.Factory.StartNew(x, CancellationToken.None,
TaskCreationOptions.None, TaskScheduler.Current);
Side Notes
A bit off topic, but be careful using any type of "blocking" on the WinForms GUI thread due to it being marked with [STAThread]
. Using await
won't block at all, but I do sometimes see it used in conjunction with some sort of blocking.
"Block" is in quotes because you technically cannot block the WinForms GUI thread. Yes, if you use lock
on the WinForms GUI thread it will still pump messages, despite you thinking it's "blocked". It's not.
This can cause bizarre issues in very rare cases. One of the reasons you never want to use a lock
when painting, for example. But that's a fringe and complex case; however I've seen it cause crazy issues. So I noted it for completeness sake.
Related Topics
Why Is a Dictionary "Not Ordered"
Random Number Generator with No Duplicates
How to Run an Exe Program from a Windows Service Using C#
How to Convert a Gi-Normous Integer (In String Format) to Hex Format? (C#)
How to Determine Programmatically Whether a Particular Process Is 32-Bit or 64-Bit
When Should I Dispose of a Data Context
How to Use Openfiledialog to Select a Folder
How to Select Distinct Rows in a Datatable and Store into an Array
At the End of an Async Method, Should I Return or Await
How to Run Another Application Within a Panel of My C# Program
How to Serialize/Deserialize to 'Dictionary<Int, String>' from Custom Xml Not Using Xelement
How to Add a Blend Behavior in a Style Setter
How to Get Difference Between Two Dates in Year/Month/Week/Day