trying to create a custom cmdlet, which takes [ref] as a parameter - c#

//powershell code
$quiotent = divRemainderQuiotent ($a) ($b) ([ref] $remainder) # I need to pass this $remainder as reference
For that I need to pass it as PSReference
//csharp code
private PSReference remainder= null;
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1044:PropertiesShouldNotBeWriteOnly"),
Parameter(
Position = 2,
Mandatory = true,
ValueFromPipeline = true)]
[ValidateNotNullOrEmpty]
public PSReference Remainder // if I don’t use this and use a value type and later change it to ref (inside C#) the result won’t bubble up, which I think is bad.
{
set { remainder = value; }
}
But now the problem becomes, the function that takes this parameter as ref integer.
protected override void ProcessRecord()
{
//main method, this is executed when cmdlet is run
int r = remainder ; //this is the problem I cannot convert PSReference to other object type (integer here).
int q = _csharpDivideRemainderQuiotent(a,b, ref r); // if I change this function to take PSReference type, I will have to make changes down the line for every function.
WriteObject(q);
} // method ProcessRecord

I haven't used PSReference before but couldn't you just do this:
protected override void ProcessRecord()
{
//main method, this is executed when cmdlet is run
int r = Convert.ToInt32(this.Remainder.Value);
int q = _csharpDivideRemainderQuiotent(a,b, ref r);
this.Remainder.Value = r;
WriteObject(q);
}

Related

Using a method call as an argument for an established method

Here is the direct text from working in Unity/C# book:
try creating a new method that takes in an int parameter and simply
prints it out to the console. No return type necessary. When you've
got that, call the method in Start, pass in a GenerateCharacter method
call as its argument, and take a look at the output.
I've tried a few different things (declaring variable in Start, creating new method and calling it, with Debug.Log in the body), but no luck. Not sure where to start.
public class LearningCurve : MonoBehaviour
{
void Start()
{
int characterLevel = 32;
int nextSkillLevel = GenerateCharacter("Spike", characterLevel);
Debug.Log(nextSkillLevel);
Debug.Log(GenerateCharacter("Faye", characterLevel));
}
public int GenerateCharacter(string name, int level)
{
//Debug.LogFormat("Character: {0} - Level: {1}", name, level);
return level + 5;
}
}
Start at the Action and Function types in C#
Action Delegate - Use it when you don't need any return type
Function Delegate - Use it when you need a return type
(Hint) You can do this:
int characterLevel = 1;
Func<string,int,int> functionStoringVariable = GenerateCharacter;
// Call the function by the variable
int result = functionStoringVariable("Spike", characterLevel);

Questions about the way out, ref, and [Out] behave in unmanaged delegate signatures

I happen to use heavy Interoperability features in some of my C# programs. In this process, I have found some odd behavior and limits to the out, ref, and [Out] options that exist. I also have found some work around to some of the limitations.
Given this, I would like to ask about why the examples given below behave the way they do. It would be nice to not have to use such tricks to work-around the limitation of using out or ref in params object[] signatures (or any params, actually). I am sure it is more likely than not there is good enough reason to not allow it even though the given work around's exist as shown below.
I will try to illustrate the behavior I refer to in the pseudo code below, comments explain most of what goes on. Feel free to ask me more specifics.
Incase it is not clear what my question is: Why am I not allowed to use out/ref tags in my parameters for my method, despite it being totally possible and working just fine if the "tricks" below are applied.
class InteropExamples {
/* note: these delegates fields must be kept alive in a real class too,
or else GC can collect them.
*/
// One method has out, the other [Out] attribute (in order, A out, B [Out])
readonly TryGetLocationA _tryGetLocationA;
readonly TryGetLocationB _tryGetLocationB;
// One method has ref IntPtr, the other IntPtr[] (in order, A ref IntPtr, B IntPtr[])
readonly IsEntityValidA _isEntityValidA;
readonly IsEntityValidB _isEntityValidB;
readonly int _mainThreadID;
public bool InvokeRequired => GetCurrentThreadId() != _mainThreadID;
public InteropExamples() {
var addressOne = IntPtr.Zero; // real address of the func here of course.
var addressTwo = IntPtr.Zero; // real address of the func here of course.
_tryGetLocationA =
Marshal.GetDelegateForFunctionPointer(addressOne, typeof(TryGetLocationA)) as TryGetLocationA;
_tryGetLocationB =
Marshal.GetDelegateForFunctionPointer(addressOne, typeof(TryGetLocationB)) as TryGetLocationB;
_isEntityValidA =
Marshal.GetDelegateForFunctionPointer(addressTwo, typeof(IsEntityValidA)) as IsEntityValidA;
_isEntityValidB =
Marshal.GetDelegateForFunctionPointer(addressTwo, typeof(IsEntityValidB)) as IsEntityValidB;
_mainThreadID = System.Diagnostics.Process.GetCurrentProcess().Threads[0].Id;
}
// This way works as expected with no limits.
// delegate void TryGetLocationA(IntPtr address, out Vector3 result);
public Vector3 GetLocationA(IntPtr address) {
Vector3 location;
// note: Invoke(_tryGetLocationA, address, out location) is not possible here.
_tryGetLocationA(address, out location);
return location;
}
// In this example, we use a trick to be able to
// use the out despite using params object[] args
// not allowing you to pass out or ref.
// delegate void TryGetLocationB(IntPtr address, [Out] Vector3[] result);
public Vector3 GetLocationB(IntPtr address) {
// note: if your delegate signature -
// has out and not the attribute [Out]
// it will fail.
var location = new Vector3[1];
// The result gets passed to the first index of the array, 0.
// Use our special invoke method with params object[] thus not allowing -
// us to use out directly like in example A.
Invoke(_tryGetLocationB, address, location);
return location[0];
}
// This way works fine and as expected.
public bool IsEntityValid_A(IntPtr entityAddress) {
// note: (bool) Invoke(_isEntityValidA, ref entityAddress) is not valid here.
return _isEntityValidA(ref entityAddress);
}
public bool IsEntityValid_B(IntPtr entityAddress) {
// note: no ref tag needed here, unlike the [Out] example.
// The array trick allows us to once again by pass the limit -
// of not being able to use ref in params object[] (or params of any kind).
var isEntityValid = (bool) Invoke(_isEntityValidB, new[] {entityAddress});
return isEntityValid;
}
// An example of why we might want to invoke unmanaged funcs with -
// a generic method using params[] object[] args, which sadly -
// with out using tricks will not allow use of out/ref signatures.
// Work arounds exist and shown in this class.
object Invoke<T>(T target, params object[] args) where T : class {
var targetDelegate = target as Delegate;
if (targetDelegate == null) {
throw new ArgumentException("Target method is not a delegate type.");
}
if (!InvokeRequired) {
return targetDelegate.DynamicInvoke(args);
}
var callback = new InvokeDelegateTarget {
Target = targetDelegate,
Args = args
};
/* notify some class to invoke your delegate */
Helper.ProcessDelegate(callback);
/* while callback.Result == null {} or what ever check you do */
return callback.Result;
}
[DllImport("kernel32.dll")]
static extern int GetCurrentThreadId();
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
delegate void TryGetLocationB(IntPtr address, [Out] Vector3[] result);
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
delegate void TryGetLocationA(IntPtr address, out Vector3 result);
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
delegate bool IsEntityValidA(ref IntPtr entityAddress);
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
delegate bool IsEntityValidB(IntPtr[] entityAddress);
}

Visual Studio 2013 Quick Watch (& Static Properties)

In debugging step through, Visual Studio 2013 shows BitConverter.IsLittleEndian is:
false: When I hover mouse on BitConverter and see the value of BitConverter.IsLittleEndian and
true: When I put it in a variable like var x = BitConverter.IsLittleEndian;
I assume BitConverter.IsLittleEndian should be already evaluated because I have called GetBytes on BitConverter so it's static constructor should be called at this point, right? What am I missing?
My code is this (I wanted to generate sequential Guid; rest is bytes of a long counter - at this version):
static Guid Id(long ticks, byte[] rest)
{
var ticksBytes = BitConverter.GetBytes(ticks).PolishEndian();
// var x = BitConverter.IsLittleEndian; // <- TESTED HERE
int a = BitConverter.ToInt32(new byte[] { ticksBytes[4], ticksBytes[5], ticksBytes[6], ticksBytes[7] }.PolishEndian(), 0);
short b = BitConverter.ToInt16(new byte[] { ticksBytes[2], ticksBytes[3] }.PolishEndian(), 0);
short c = BitConverter.ToInt16(new byte[] { ticksBytes[0], ticksBytes[1] }.PolishEndian(), 0);
return new Guid(a, b, c, rest.PolishEndian(true).ToArray());
}
static byte[] PolishEndian(this byte[] ba, bool reverse = false)
{
var flag = reverse ? BitConverter.IsLittleEndian : !BitConverter.IsLittleEndian;
if (flag) return ba.Reverse().ToArray();
return ba;
}
Note that in this case IsLittleEndian is actually a field and not a property. That has an effect on how the EE is able to process the value.
I tried this out locally and this is the behavior I saw
First i stepped until the cursor hit the var ticksBytes line. At that point I observed that IsLittleEndian == false. This is actually expected at this point. The EE does not always need to force a static constructor to run in order to read fields. Hence it is just reading the value as is and because no other code for BitConverter has run the value is false
Immediately after stepping over that line I observe that IsLittleEndian == true. The CLR ran the static constructor in order to execute the GetBytes method and hence that set the field. The EE was then reading the set field.
Note that you can recreate this example with your own code. For example
static class Test {
static readonly bool example;
static Test() {
example = true;
}
internal static void Go() {
// example == true
}
}
class Program {
static void Main() {
// Test.example == false;
Test.Go();
}
}
Earlier I mentioned that the EE didn't always need to execute a static constructor in order to read fields. One case where it often needs to is when reading static fields off of a generic type. The storage for a static field of a generic type isn't created essentially until the CLR instantiates an instance of the type. Hence in order to read a field off of a generic type which hasn't yet been used the EE will create an instance under the cover in order to force the CLR to read it. For example
static class Test<T>
{
static readonly bool example = false;
static Test()
{
example = true;
}
}
If you add this to your program and then evaluate the following in the watch window
Test<int>.example
you will find that the value is true clearly indicating the cctor ran

Pass a bool Foo(params[]) as method Argument

There are times that a method needs to be run several times until it validates. In my case there are expressions like bar.Name.Equals("John Doe") which I want to run and run until this expression validates.
Something like:
bool succeeded = TryUntillOk(bar.Name.Equals("John Doe"), 15, 100);
where TryUntillOk would be a method that runs this expression 15 times with a sleep of 100ms between each call.
I read this excellent list of answers to similar issues but in my case there is no standar delegate that this TryUntillOk method would accept.
The title of the question is not constructive. Feel free to edit it :)
You are probably looking for something like this:
bool TryRepeatedly(Func<bool> condition, int maxRepeats, TimeSpan repeatInterval)
{
for (var i = 0; i < maxRepeats; ++i)
{
if (condition()) return true;
Thread.Sleep(repeatInterval); // or your choice of waiting mechanism
}
return false;
}
Which would be invoked as follows:
bool succeeded = TryRepeatedly(() => bar.Name.Equals("John Doe"),
15,
TimeSpan.FromMilliseconds(100));
The only interesting part here is that you specify the condition as a Func<bool>, which is a delegate to a method that takes no parameters and returns a boolean. Lambda expression syntax allows you to trivially construct such a delegate at the call site.
You have to adapt the invokation. #Jon's answer has lambda invoaction, this version separates the comparand from the delegate
using System;
using System.Threading;
namespace test
{
class something
{
public String Name;
}
class Program
{
private delegate bool TryableFunction(String s);
private static bool TryUntillOk(TryableFunction f, String s, int howoften, int sleepms)
{
while (howoften-->0)
{
if (f(s)) return true;
Thread.Sleep(sleepms);
}
return false;
}
static void Main(string[] args)
{
something bar=new something();
bar.Name="Jane Doe";
bool succeeded = TryUntillOk(bar.Name.Equals,"John Doe", 15, 100);
Console.WriteLine("Succeeded with '{0}': {1}",bar.Name,succeeded);
bar.Name="John Doe";
succeeded = TryUntillOk(bar.Name.Equals,"John Doe", 15, 100);
Console.WriteLine("Succeeded with '{0}': {1}",bar.Name,succeeded);
}
}
}
You can check it
delegate void d_name(string s);
d_name obj =new d_name(bar.Name.Equals);
bool succeeded = TryUntillOk(obj("John Doe"), 15, 100);
TryUntillOk(obj d,type parameter2,type parameter3 )
{
//do your work
}

C# lambda ref out

I'm trying to do this, but it doesn't work. Some suggestions?
int test_i = 0;
DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(test_i);
test_i <- still is 0 and not 3!!!
public void DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(int i)
{
DisableUi();
m_commandExecutor.ExecuteWithContinuation(
() =>
{
// this is the long-running bit
ConnectToServer();
i = 3; <--------------------------
// This is the continuation that will be run
// on the UI thread
return () =>
{
EnableUi();
};
});
}
Why I can't set test_i to 3? I also tried ref and out, but it doesn't work.
What can I do to fix it?
EDIT
I've tried this, but ouside of this method dataSet still is empty.
public static void Select(DataGridView dataGridView, ref DataSet dataSet, params object[] parameters)
{
var _dataSet = dataSet;
AsyncCommandExecutor commandExecutor = new AsyncCommandExecutor(System.Threading.SynchronizationContext.Current);
commandExecutor.ExecuteWithContinuation(
() =>
{
// this is the long-running bit
_dataSet = getDataFromDb(parameters);
// This is the continuation that will be run on the UI thread
return () =>
{
dataGridView.DataSource = _dataSet.Tables[0].DefaultView;
};
});
dataSet = _dataSet;
}
When passing the variable using the ref keyword, you can't use it inside a lambda expression. Try using a local variable inside the lambda and assign the ref variable outside it, if possible (somewhat simplified example):
private static void Main(string[] args)
{
int i = 0;
DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(ref i);
Console.WriteLine(i);
}
public static void DoSomethingThatTakesAgesAndNeedsToUpdateUiWhenFinished(ref int i)
{
int temp = i;
Thread t = new Thread(() =>
{
temp = 3; // assign the captured, local variable
});
t.Start();
t.Join();
i = temp; // assign the ref parameter
}
Update
In response to the updated answer: your problem is that _dataSet inside the lambda expression is not the same variable as dataSet outside the lambda expression. What you could do is the following:
class DataSetContainer
{
public DataSet DataSet { get; set; }
}
Now we have a reference type with a property that we can safely modify inside the lambda expression:
public static void Select(DataGridView dataGridView,
DataSetContainer dataSetContainer,
params object[] parameters)
{
AsyncCommandExecutor commandExecutor = new AsyncCommandExecutor(System.Threading.SynchronizationContext.Current);
commandExecutor.ExecuteWithContinuation(
() =>
{
// this is the long-running bit
dataSetContainer.DataSet = getDataFromDb(parameters);
// This is the continuation that will be run on the UI thread
return () =>
{
dataGridView.DataSource = _dataSet.Tables[0].DefaultView;
};
});
}
}
In the above code, the lambda expression will update the DataSet property of the DataSetContainer instance that is passed to the Select method. Since you are not modifying the passed argument itself but only a member of that instance there is no need for the ref keyword, and we also get around the closure issue.
Update 2
And now when I switched on my brain, I realize that the Select method makes an asynchronous call. It is quite likely as the code looks that the last line is the Select method will be executed long before _dataSet is being assigned, and as a result it will be null. To get around this you probably want to look into using some sort of signaling mechanism (such as ManualResetEvent or AutoResetEvent) to know when the assignment is done.
The i variable in the lambda expression refers to the parameter i of the method. As a workaround, you can make it to refer to a global variable (dirty solution).
By the way, you can't capture ref and out variables in lambdas, but you can have them as parameters. You need to change the signature of your delegate and the implementation of the method receiving the delegate, which might not be suitable:
(out int i) => { i = 10; }

Categories

Resources