Pattern Matching Enhancement: Switch Pattern - .net-core-3.0

Just had a look at the "new" C# 8.0 Features
So I tried to rewrite the following code
private static void RunExample(ExampleCode exampleCode)
{
switch(exampleCode)
{
case ExampleCode.DefaultInterfaceMethod:
RunDefaultInterfaceMethodExample();
break;
case ExampleCode.PatternMatchingEnhancements:
RunPatternMatchingEnhancementsExample();
break;
}
}
to this:
private static void RunExample(ExampleCode exampleCode)
{
exampleCode switch
{
ExampleCode.DefaultInterfaceMethod => RunDefaultInterfaceMethodExample(),
ExampleCode.PatternMatchingEnhancements => RunPatternMatchingEnhancementsExample()
};
}
However, I am getting the following compile error:
Only assignment, call, increment, decrement, await, and new object
expressions can be used as a statement.
How can I rewrite this in the new syntax?

As pointed in the comments the new switch based pattern matching is expecting result to be returned.
In F# because everything is an expression, the void type is actually a valid return type for an expression and this would have worked.
In case like yours i think it is best to use the old code, but if you really want to use the new syntax you can do something like this:
Action methodToExecute = exampleCode switch
{
ExampleCode.DefaultInterfaceMethod => RunDefaultInterfaceMethodExample,
ExampleCode.PatternMatchingEnhancements => RunPatternMatchingEnhancementsExample,
_ => throw new NotImplementedException()
};
methodToExecute();
(this will work only if the methods you are executing for each case have the same definitions)
It is good practice to use exhaustive pattern, this is why i am using the last case with the underscore.
In C# enum values are compiled to integers and even if your switch handles all enum labels the compiler still does not know you have handled all cases and when you add new label to the enum you won't have proper warrning that you are have unhandled case.
Whenever you are using enums it is best to use default case where all unhandled cases will fall in.

Related

Making AutoMoq return Fixture-created values for methods

I'd like to explore wether we can save time by setting that all Moq-mocks created by AutoMoq should by default return Fixture-created values as method return values.
This would be beneficial when doing a test like the following:
[TestMethod]
public void Client_Search_SendsRestRequest()
var client = fixture.Create<Client>();
// Could be removed by implementing the mentioned functionality
Mock.Of(JsonGenerator).Setup(j => j.Search(It.IsAny<string>())).Returns(create("JsonBody")));
client.Search(fixture.Create("query"));
Mock.Of(client.RestClient).Verify(c => c.Execute(It.IsAny<RestRequest>()));
Mock.Of(client.RestClient).Verify(c => c.Execute(It.Is<RestRequest>(r => record(r.Body) == record(client.JsonGenerator.Search(query)))));
}
Note that the generated values must be cached inside (?) the proxies, we want the same value "frozen" in order to check. Also, setting up the mock with Setup should override the created value.
So, how can we modify AutoMoq mocks to do this?
A simple test verifying that it works could be:
[TestMethod]
public void MockMethodsShouldReturnCreatedValues()
{
Guid.Parse(new Fixture().Create<ITest>().Test());
}
public interface ITest
{
string Test();
}
Definitely possible, just use the AutoConfiguredMoqCustomization instead of the AutoMoqCustomization. The mocks will use the fixture to generate returns values for all its methods, properties and indexers (*).
Properties will be evaluated eagerly, whereas indexers/methods' return values will be evaluated and cached when invoked for this first time.
(*) There are two exceptions to this rule - the customization cannot automatically setup generic methods or methods with ref parameters, as explained here. You'll have to set those up manually, with the help of the .ReturnsUsingFixture method.

Calling FluentMigrator methods inside Execute.WithConnection action

Calling FluentMigrator's builder methods while inside the action that I pass to Execute.WithConnection causes a null reference exception to be thrown.
What I am trying to do is select some data so that I may manipulate it in c#, as that is easier than manipulating it in T-SQL, and use the result of my c# operations to update the data or insert new data (to be more specific, I need to pick one query string parameter out of a stored url string and insert it somewhere else).
The only way I see to select data within a migration is to use Execute.WithConnection and retrieve the data myself (FluentMigrator provides no helpers for selecting data), but if I try to use any fluent migrator expression in the action I pass to Execute.WithConnection a null reference exception is thrown.
Here is a boiled down version of my code:
[Migration(1)]
public class MyMigration : Migration
{
public void Up()
{
Execute.WithConnection(CustomDml);
}
public void CustomDml(IDbConnection conn, IDbTransaction tran)
{
var db = new NPoco.Database(conn).SetTransaction(tran); // NPoco is a micro-ORM, a fork of PetaPoco
var records = db.Fetch<Record>("-- some sql"); // this is immediately evaluated, no reader is left open
foreach (var r in records) {
var newValue = Manipulate(r.OriginalValue);
Insert.IntoTable("NewRecords").Row(new { OriginalValueId = r.Id, NewValue = newValue }); // <-- this line causes the exception
}
}
public void Down() {}
}
The line that calls Inser.IntoTable causes a null exception to be thrown from line 36 of FluentMigrator\Builders\Insert\InsertExpressionRoot.cs - it appears that the _context variable may be null at this point but I do not understand why this is. (when testing Create.Table, e.g., it occurs on line 49 of FluentMigrator\Builders\Create\CreateExpressionRoot.cs)
Any help would be appreciated. Perhaps there is disagreement on whether DML is appropriate in a migration, and I am open to suggestions, but this scenario has come up twice this week alone. For now I am simply performing the insert using my micro-ORM within the action rather than FluentMigrator and that does work, but it seems like what I am trying to do should work.
When using the Execute.WithConnection expression all you get is the db connection and the transaction.
Using Execute.WithConnection creates an PerformDBOperationExpression expression. When processing the expression, a processor calls the Operation property (an example in the SqlServerProcessor) and the processor does not have a reference to the MigrationContext. But even if it did have access to the MigrationContext, when FluentMigrator has come to the processing stage, it is already too late. You would be trying to process expressions in a expression and at the moment FluentMigrator is not built to handle that type of nesting.
An alternative would be to make the connection string available in the migration context, see this issue: https://github.com/schambers/fluentmigrator/issues/240
Would that be a better approach?

"Bool" not found in .NET application running on Mono/XPS

I am incredibly new to .NET and Mono. I have a .NET 4 application that I am trying to run locally, and I'm getting a compilation error when I try to run it (using xps4 on Ubuntu). At the end of the stacktrace it says:
/tmp/jeremy-temp-aspnet-0/3b8f3547/App_Web_635c7158_48.cs(32,21): error CS0246: The type or namespace name `bool' could not be found. Are you missing a using directive or an assembly reference?
Does that mean that it doesn't recognize the boolean type? A Google search wasn't much help.
Update - Here's the code:
public virtual #bool ShowRecentPlans {
get {
return ((#bool)(this.GetPropertyValue("ShowRecentPlans")));
When you prefix an identifier (like a type name) with #, you're telling the compiler that, even though it looks like a reserved word, it refers to something defined in your program.
Unless you have something defined somewhere like
public class #bool
{
...
}
then this isn't going to work.
Try
public virtual bool ShowRecentPlans {
get {
return (bool)(this.GetPropertyValue("ShowRecentPlans"));
}
}
For instance, if you wanted to use the keyword new as an identifier, you could:
int new = 5; /// error!
int #new = 5; /// compiles
# is of course also used to tell the compiler how a string should be interpreted.
// throws an error because \p and \m look like formatting sequences
var path = "c:\pub\myFile.txt";
// compiles
var path = #"c:\pub\myFile.txt";
Also, I just have to ask: what made you use #bool instead of bool to start with?
(And, for the record, using a keyword as an identifier is a very, very bad idea.)
Your return type should be bool instead of #bool.

Flex: AMF and Enum Singletons – can they play well together?

I'm using Python+PyAMF to talk back and forth with Flex clients, but I've run into a problem with the psudo-Enum-Singletons I'm using:
class Type {
public static const EMPTY:Type = new Type("empty");
public static const FULL:Type = new Type("full");
...
}
When I'm using locally created instances, everything is peachy:
if (someInstance.type == Type.EMPTY) { /* do things */ }
But, if 'someInstance' has come from the Python code, it's instance of 'type' obviously won't be either Type.EMPTY or Type.FULL.
So, what's the best way to make my code work?
Is there some way I can control AMF's deserialization, so when it loads a remote Type, the correct transformation will be called? Or should I just bite the bullet and compare Types using something other than ==? Or could I somehow trick the == type cohesion into doing what I want?
Edit: Alternately, does Flex's remoting suite provide any hooks which run after an instance has been deserialized, so I could perform a conversion then?
Random thought: Maybe you could create a member function on Type that will return the canonical version that matches it?
Something like:
class Type {
public static const EMPTY:Type = new Type("empty");
public static const FULL:Type = new Type("full");
...
// I'm assuming this is where that string passed
// in to the constructor goes, and that it's unique.
private var _typeName:String;
public function get canonical():Type {
switch(this._typeName) {
case "empty": return EMPTY;
case "full": return FULL;
/*...*/
}
}
}
As long as you know which values come from python you would just convert them initially:
var fromPython:Type = /*...*/
var t:Type = fromPython.canonical;
then use t after that.
If you can't tell when things come from python and when they're from AS3 then it would get pretty messy, but if you have an isolation layer between the AS and python code you could just make sure you do the conversion there.
It's not as clean as if you could control the deserialization, but as long as you've got a good isolation layer it should work.

best way to store / lookup name value pairs

I have a list of error codes I need to reference, kinda like this:
Code / Error Message
A01 = whatever error
U01 = another error
U02 = yet another error type
I get the Code returned to me via a web service call and I need to display or get the readable error. So I need a function when passed a Code that returns the readable description. I was just going to do a select case but thought their might be a better way. What is the best way / most effieient way to do this?
Use a Dictionary, (in C#, but the concept and classes are the same):
// Initialize this once, and store it in the ASP.NET Cache.
Dictionary<String,String> errorCodes = new Dictionary<String,String>();
errorCodes.Add("A01", "Whatever Error");
errorCodes.Add("U01", "Another Error");
// And to get your error code:
string ErrCode = errorCodes[ErrorCodeFromWS];
You would use a dictionary. A dictionary uses a hashmap internally for performance, so it is good in that regard. Also, because you want this to go as quickly as possible by the sounds of it, I would statically initialize it in its own class instead of, for example, in an XML file or slimier. You would probably want something like:
public static class ErrorCodes
{
private static Dictonary<string, string> s_codes = new Dicontary<string, string>();
static ErrorCodes()
{
s_codes["code"] = "Description";
s_codes["code2"] = "Description2";
}
public static string GetDesc(string code)
{
return s_codes[code];
}
}
That way, if you wanted to move the back end to a file instead of being static, then you could.

Resources