How can I coerce an integer to an enum type in PowerShell? - powershell

Read carefully before you answer! I want to cast an integer to an enum type where the integer value is not actually defined in the enum. In VB.Net, it is possible to directly cast any integer to an integer-based enum type using DirectCast. Is there some way to accomplish this natively in PowerShell?
I need to do this in PowerShell in order to call a method on an Office Interop object (Access.Application.SysCmd) which takes an enumeration value as its first argument (AcSysCmdAction), but where the actual value I need to pass (603 for the undocumented export to accde action) is not included in the PIA enum definition. PowerShell's built-in type conversion cause it to convert either a number or a string the applicable enumeration type, but it will not coerce an int value that is not in the enum. Instead it throws an invalid conversion exception. Right now I'm resorting to a dynamically compiled ScriptControl which calls SysCmd via VBScript, but I'd like to keep everything in PowerShell if possible.

You could call the Enum class's ToObject method:
$day = [Enum]::ToObject([DayOfWeek], 90)

Well, I just figured out a way. In PowerShell, it appears enum objects have a property called "value__" which can be directly set to any value!
#Create a variable with the desired enum type
$ops = [System.Text.RegularExpressions.RegexOptions]0
#Directly set the value__ property
$ops.value__ = 3450432

Related

The name 'string' isn't a type and can't be used in an 'is' expression

During unit testing of a function returning different types of objects, I need to check if the type of returned object is the same as expected. Therefore, I need to pass multiple classes inside a variable. Then I need to use this variable with the is operator to check types.
final string = String;
assert('foo' is string);
But I am getting
error: The name 'string' isn't a type and can't be used in an 'is' expression.
I read somewhere that a library called Dart:mirrors can solve this problem but I haven't seen an actual example.
In unit testing, you know the expected answer. There shouldn't be a need to make your types variables.
Instead, just assert with the strong typed
assert('foo' is String);
I found the answer. The trick to create an instance of the type that I want to assert, then use runtimeType property.
If a class is called User from a.dart and another one is also called User from b.dart, runtimeType won't be the same
final string = 'anything'.runtimeType;
assert('foo'.runtimeType is string);

Dictionary with Tuple key in Powershell

I need to create a Dictionary with Tuple key in Powershell.
Exactly like I can do in C# like this:
var test = new Dictionary<(int, bool), int>();
// Add
test.Add((1, false), 5);
// Get
int a = test[(1, false)];
(Taken from Hashtable with MultiDimensional Key in C#)
Is it possible? (I am running Powershell version 5.1.18362.145.)
Thanks!
To add to Jeroen Mostert's excellent comments on the question:
The following is a direct translation of your C# code to PowerShell v5.1+ code:
using namespace System.Collections.Generic
# Construct
$test = [Dictionary[[ValueTuple[int, bool]], int]]::new()
# Add
$test.Add([ValueTuple[int, bool]]::new(1, $false), 5)
# Get
$test[[ValueTuple[int, bool]]::new(1, $false)]
using namespace is a PSv5+ feature akin to C#'s using construct: it allows you to refer to the types in the specified namespace by their mere names, without namespace qualification.
As Jeroen points out, PowerShell has no syntactic sugar for value-tuple instances, so that C# tuple literal (1, false) must be represented as an explicit constructor call: [ValueTuple[int, bool]]::new(1, $false).
The alternative is to use the static Create method on the non-generic System.ValueType base type, in which case the tuple component types are inferred:
[ValueTuple]::Create(1, $false)
Given that PowerShell exposes a type's constructors via the static ::new() method on the type itself, you can simplify the code by instantiating the specific tuple type once and reusing it via a variable (ignore the broken syntax highlighting):
using namespace System.Collections.Generic
# Instantiate the concrete tuple type (type arguments locked in).
$tupleType = [ValueTuple[int, bool]]
# Construct the dictionary with the tuple type as the key.
# See explanation below.
$test = [Dictionary`2].MakeGenericType($tupleType, [int])::new()
#`# Add
$test.Add($tupleType::new(1, $false), 5)
# Get
$test[$tupleType::new(1, $false)]
The downside is that the dictionary construction becomes more awkward, because PowerShell type literals such as [Dictionary[[ValueTuple[int, bool]], int]] must not have non-literal components.
To work around that, System.Type.MakeGenericType is used to construct the closed generic type from the dynamically specified type arguments; note the need to specify the arity (`2) of the open generic type on which .MakeGenericType() is invoked.

Get a type identified by a string in the Scala macros

I have a bunch of strings (essentially names of java.lang. classes and some custom classes). In the macro I need to add the type to the function:
q"""propKey[${resolveType(c)(argType)}]($name, classOf[$argType])"""
where argType is String.
So far I tried q"$argType" - but that adds the weird signature propKey[String("java.lang.Integer")](...)
with c.universe.TypeName- there's no method to get a c.universe.Type instance.
c.mirror.staticClass("java.lang.String").toType

Casting to a type held in a variable

I am attempting to cast a variable to a different type that is held in a variable or is the return type of a function. Here is the idea:
let i = 1 as type(of: 3.14)
But when I do this, I get a couple of errors:
Use of undeclared type 'type'
Consecutive statements on a line must be separated by ';' (This inserts a semi-colon between type and (of: 3.14))
And a warning:
Expression of type (of: Double) is unused
How to I cast a value to a type that is held in a variable?
Swift (currently) requires the Type assignment at compile time. You can do some things like this, but you will need to write a converter for each type combination you want to use, e.g:
func convertType(from item: Int) -> Float {
return Float(item)
}
var item: Float = convertType(from: 1)
I would caution going down this road and try and get used to Swift's way of doing things. If you absolutely need it you should be able to use some generic functions with a protocol like FloatConvertable to handle this more simply.
The Swift grammar doesn't allow for these types of expressions. The expression after as must be the name of a type, ie. 1 as Double (though, as vadian points out, you can't cast numeric types to each other, so a better example would be mySubClassObject as MySuperClass). Swift is a strongly typed language, which means it needs to know the types of all variables at compile time.

Why doesn't inout pass by reference?

I'm doing something like this:
someFunction(&myClass)
where someFunction sorts an array on myClass.
someFunction(inout someclass:ClassA) {
someClass.sort({$0.price > $1.price})
}
If I print myClass after the function call, I notice the array is still unsorted. From what I know, Swift passes values by copy. But when I use inout, shouldn't it change to pass by reference?
This is because class instances and functions are reference types. Ints, structs, and everything else are value types. When you pass a reference type into a function as a parameter, you are already going to be referencing that instance. When you pass a value type as a parameter, the function gets a copy of that variable (by default), so inout is usually (see edit) only needed if you want to alter a value type from inside of a function.
Altering a class instance without & or inout:
More details
When you create a reference type var t = myClass(), you're really creating a variable t that is a pointer to a myClass instance in memory. By using an ampersand &t in front of a reference type, you are really saying "give me the pointer to the pointer of a myClass instance"
More info on reference vs value types: https://stackoverflow.com/a/27366050/580487
EDIT
As was pointed out in the comments, you can still use inout with reference types if you want to alter a pointer, etc, but I was trying to shed light on the general use case.
Below is an example of sorting an array inside of a function:
If you post your code here, it would be more meaningful. BTW, look at below links that might helpful for you,
https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html#//apple_ref/doc/uid/TP40014097-CH10-ID173
https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/doc/uid/TP40014097-CH34-ID545