.NET Core 3.1 v .NET 6.0 - c#

I got all excited on the release of Visual Studio 2022, C# 10 and .NET 6.0 and downloaded and installed the community edition and tested a project I am working on. I changed the target framework to 6.0 and performed a clean build. Great, everything built as expected.
So, onwards and upwards and ran the project. The very first test failed. I must say I was surprised. I started digging around and was really surprised to find a difference between .NET Core 3.1 and .NET 6.0.
Here is a sample program:
public class Program
{
public static readonly string CTCPDelimiterString = "\x0001";
public static readonly char CTCPDelimiterChar = '\x0001';
public static void Main(string[] args)
{
string text = "!sampletext";
Console.Write(" Using a char: ");
if (text.StartsWith(CTCPDelimiterChar) && text.EndsWith(CTCPDelimiterChar))
{
Console.WriteLine("got CTCP delimiters");
}
else
{
Console.WriteLine("did not get CTCP delimiters");
}
Console.Write("Using a string: ");
if (text.StartsWith(CTCPDelimiterString) && text.EndsWith(CTCPDelimiterString))
{
Console.WriteLine("got CTCP delimiters");
}
else
{
Console.WriteLine("did not get CTCP delimiters");
}
}
}
Using a target framework of 'netcoreapp3.1' I got the following output:
Using a char: did not get CTCP delimiters
Using a string: did not get CTCP delimiters
Using a target framework of 'net6.0' I got the following output:
Using a char: did not get CTCP delimiters
Using a string: got CTCP delimiters
So, I can only assume that it is a unicode setting but I cannot find it anywhere (if there is one). My understanding is that all strings are UTF16 but why the difference between frameworks.
And yes, I can see the bug in my code, it should be a char anyway but it was working fine using 'netcoreapp3.1'.
Can anyone shed some light on this please.

After .Net Core 3, you must highlight your comparison mode by StringComparison code.
change
if (text.StartsWith(CTCPDelimiterString) && text.EndsWith(CTCPDelimiterString))
with
if (text.StartsWith(CTCPDelimiterString, StringComparison.Ordinal) && text.EndsWith(CTCPDelimiterString, StringComparison.Ordinal))

Related

DotSpatial (C#) re-projections - 'InitializeExternalGrids' causes .Net to 'freeze'

I am trying to apply an NTv2 gridshift package (OSTN15 from the UK Ordnance Survey) to some DotSpatial re-projections. This is the code I have so far:
const string Proj4_4326 = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs";
const string OSTN15 = #"+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +units=m +no_defs +nadgrids=D:\directory\OSTN15_NTv2_OSGBtoETRS.gsb";
static void Main(string[] args)
{
double[] polygonPoints = new double[2] { 530624.974, 178388.464 };
double[] zp = new double[10];
ProjectionInfo srcProjection = ProjectionInfo.FromProj4String(OSTN15);
ProjectionInfo desProjection = ProjectionInfo.FromProj4String(Proj4_4326);
GridShift.InitializeExternalGrids(#"D:\directory\OSTN15-NTv2", false);
Reproject.ReprojectPoints(polygonPoints, zp, srcProjection, desProjection, 0, 1);
}
The code gets to the 'Gridshift.InitializeExternalGrids' and 'hangs'. It appears to be processing but after 40 minutes it has built up to 2G RAM used and about 25% CPU usage constant.
I'm assuming that it should not take this long to initialise the grids and that something is going wrong.
I am using DotSpatial.Projections 1.9.0 added using NuGet, there is nothing else in the project other than this code, it is a .NET Framework 4.7.2 console app, x64 platform target (I tried x86 also).
Has anyone else had this issue or can offer any advice .
Thanks.

got unexpected named argument error when running csharp code on visual studio

I tried to run the csharp code in Visual Studio Code for Mac, I have scripts installed and added to PATH.
It gives me below error and code cannot run.
[Running] scriptcs "/var/folders/sr/5jzw91rn4g3cc2b0xyhw0j100000gq/T/tempCodeRunnerFile.csharp"
Unexpected named argument: var/folders/sr/5jzw91rn4g3cc2b0xyhw0j100000gq/T/tempCodeRunnerFile.csharp
This is the question linked: Getting error: /bin/sh scriptcs: command not found
The OS version is 10.14.6(18G87) Please see attached screenshot.
The Visual Studio Code version is below:
Version: 1.38.1
Commit: b37e54c98e1a74ba89e03073e5a3761284e3ffb0
Date: 2019-09-11T13:31:32.854Z
Electron: 4.2.10
Chrome: 69.0.3497.128
Node.js: 10.11.0
V8: 6.9.427.31-electron.0
OS: Darwin x64 18.7.0
minimal reproducible example:
Open Visual Studio Code and create a new File with below code:
using System;
using System.Collections.Generic;
class Test
{
static void Main()
{
foreach (int fib in Fibs(6))
Console.Write (fib + " ");
}
static IEnumerable<int> Fibs (int fibCount)
{
for (int i = 0, prevFib = 1, curFib = 1; i < fibCount; i++)
{
yield return prevFib;
int newFib = prevFib+curFib;
prevFib = curFib;
curFib = newFib;
}
}
}
and then click Run Code on top right in Visual Studio Code.
This is a bug in PowerArgs, it recognizes an argument started with slash as an option, so you need split the command into two steps.
cd "/var/folders/sr/5jzw91rn4g3cc2b0xyhw0j100000gq/T"
scriptcs "tempCodeRunnerFile.csharp"
[Update]
scriptcs is a csharp code runner, to make it work, at least you need one line to call the entry method.
...
class Test
{
public static void Main() // Public
{
...
}
}
Test.Main(); // Run it

c# File.Exists always return false using value property

During debugging I found something annoying.
I have a file existing on my drive, I'm wondering why if I use the file exists function it always returns false, using property value. I try also in Immediate Window here are the results
ACGateLoginSystem.MAP_PATH == #"‪D:\Capture001.png" | true
?File.Exists(ACGateLoginSystem.MAP_PATH) | false
?File.Exists("D:\\Capture001.png") | true
I'm using windows 10 latest build, and visual studio 2017.
Following is working for me.
namespace ConsoleApplication1
{
class LoginSystem
{
public string MAP_PATH { get; set; }
}
class Program
{
static void Main(string[] args)
{
LoginSystem ACGateLoginSystem = new LoginSystem();
ACGateLoginSystem.MAP_PATH = #"D:\1.png";
if (File.Exists(ACGateLoginSystem.MAP_PATH))
Console.WriteLine("File Exists");
if (File.Exists("D:\\1.png"))
Console.WriteLine("File Exists - with direct path");
Console.ReadLine();
}
}
}
Output:
The backslash character \ is a special character in C# (and any C-like language). It is used in conjunction with a second one to define special character. Thus, this would work:
File.Exists("D:\\Capture001.png")
and this should work
File.Exists(#"D:\Capture001.png")
and this won't work
File.Exists("D:\Capture001.png")

.Net Core Library in .Net Standard: Core Long Path Handling

How would one use a .Net Core library in a regular .Net application? I came across this Hanselman article that explains I should be using a .Net Standard library. Problem is, my code only works in a Core Library (afaik).
The below method works in Core but not in a Standard library. It appears that Core handles long paths (over the 250 char limit) better than regular .Net solutions (Background).
Is there a way to use a Core library in a regular .Net library?
private static List<FileInfo> FastGetFileList(string myBaseDirectory, string searchString = "*.*")
{
var dirInfo = new DirectoryInfo(myBaseDirectory);
return dirInfo.EnumerateDirectories()
.AsParallel()
.SelectMany(di => di.EnumerateFiles(searchString, SearchOption.AllDirectories)).ToList()
.Union(dirInfo.EnumerateFiles(searchString)).ToList();
}
Full Solution for Testing
This will fail in a regular console app and also doesn't work when called from a .Net Standard 2.0 library. In a Core console app, it will work.
private string path =
#"\\GREATER THAN 250 CHARACTERS NETWORK FOLDER LOCATION"
;
static void Main(string[] args)
{
var temp = FastGetFileList(path);
Console.WriteLine("Success");
Console.ReadLine();
}
private static List<FileInfo> FastGetFileList(string myBaseDirectory, string searchString = "*.*")
{
var dirInfo = new DirectoryInfo(myBaseDirectory);
return dirInfo.EnumerateDirectories()
.AsParallel()
.SelectMany(di => di.EnumerateFiles(searchString, SearchOption.AllDirectories)).ToList()
.Union(dirInfo.EnumerateFiles(searchString)).ToList();
}

Connecting from C# to Accumulo

I am new to working with Accumulo. I need to read/write data from a remote Accumulo through C#.
The only code sample/documentation for C#, I have found is -
Accumulo createBatchScanner range not working as expected
I attempted to compile the code in Xamarin Studio, on a Mac.
The issue I am encountering is with this line:
AccumuloProxy.Client client = new AccumuloProxy.Client(protocol);
Error CS0246: The type or namespace name AccumuloProxy' could not be found. Are you missingorg.apache.accumulo.proxy.thrift' using directive? (CS0246) (AccumuloIntegratorPrototype)
Where can I find the DLLs to add to my CSharp project related to AccumuloProxy client?
Is there a way I can generate the same?
Here is a code fragment:
namespace AccumuloIntegratorPrototype
{
class MainClass
{
static byte[] GetBytes(string str)
{
return Encoding.ASCII.GetBytes(str);
}
static string GetString(byte[] bytes)
{
return Encoding.ASCII.GetString(bytes);
}
public static void Main (string[] args)
{
try
{
/** connect **/
TTransport transport = new TSocket("xxx.xx.x.xx", 42424);
transport = new TFramedTransport(transport);
TCompactProtocol protocol = new TCompactProtocol(transport);
transport.Open();
AccumuloProxy.Client client = new AccumuloProxy.Client(protocol);
Thanks to all for the pointers.
Was able to complete my project.
These are my notes.
A. Versions:
Accumulo 1.5
Thrift 0.90
Mono 3.2.5
B. Strategy/option used to connect to Accumulo from C#:
Accumulo Proxy API
C. Accumulo Proxy with C# bindings:
Performed the following actions on a node running Accumulo
1. Installed Mono 3.2.5
2. Installed Thrift 0.90
3. Configured Accumulo proxy service
Modified the file $ACCUMULO_HOME/proxy/proxy.properties;
Specifically updated the instance name, and zookeeper
4. Started the proxy daemon-
${ACCUMULO_HOME}/bin/accumulo proxy -p ${ACCUMULO_HOME}/proxy/proxy.properties
5.Generated the c# bindings, using the proxy.thrift IDL file
thrift --gen csharp $ACCUMULO_HOME/proxy/thrift/proxy.thrift
This resulted in the creation of a directory called gen-csharp under ${ACCUMULO_HOME}/proxy/thrift/
6. The files under gen-csharp are needed in the C# project, in section D, below.
7. Thrift.dll, is also needed.
D. C# project - Accumulo Client:
1. Created a project of type library.
2. Added the files under gen-csharp in step C5, above to the library
3. Added reference to thrift.dll
4. Built the library
E. Connecting to Accumulo from C#
In the C# project that reads/writes to Accumulo,
1. Added reference - thrift.dll
2. Added reference to the library built in section D, above
3. On the Accumulo server, started the proxy (refer step C4, above)
Here is some sample code, to read data, to try this functionality out..
using System;
using System.Text;
using System.Collections.Generic;
using Thrift.Protocol;
using Thrift.Transport;
namespace AccumuloIntegratorPrototype
{
class MainClass
{
static byte[] GetBytes(string str)
{
return Encoding.ASCII.GetBytes(str);
}
static string GetString(byte[] bytes)
{
return Encoding.ASCII.GetString(bytes);
}
public static void Main (string[] args)
{
try
{
String accumuloProxyServerIP = "xxx.xxx.x.xx";//IP
int accumuloProxyServerPort = 42424;//Port Number
TTransport transport = new TSocket(accumuloProxyServerIP, accumuloProxyServerPort);
transport = new TFramedTransport(transport);
TCompactProtocol protocol = new TCompactProtocol(transport);
transport.Open();
String principal = "root";//Application ID
Dictionary<string, string> passwd = new Dictionary<string,string>();
passwd.Add("password", "xxxxx");//Password
AccumuloProxy.Client client = new AccumuloProxy.Client(protocol);
byte[] loginToken = client.login(principal, passwd);//Login token
//{{
//Read a range of rows from Accumulo
var bScanner = new BatchScanOptions();
Range range = new Range();
range.Start = new Key();
range.Start.Row = GetBytes("d001");
//Need the \0 only if you need to get a single row back
//Otherwise, its not needed
range.Stop = new Key();
range.Stop.Row = GetBytes("d001\0");
bScanner.Ranges = new List<Range>();
bScanner.Ranges.Add(range);
String scanId = client.createBatchScanner(loginToken, "departments", bScanner);
var more = true;
while (more)
{
var scan = client.nextK(scanId, 10);
more = scan.More;
foreach (var entry in scan.Results)
{
Console.WriteLine("Row = " + GetString(entry.Key.Row));
Console.WriteLine("{0} {1}:{2} [{3}] {4} {5}", GetString(entry.Key.Row), GetString(entry.Key.ColFamily), GetString(entry.Key.ColQualifier), GetString(entry.Key.ColVisibility), GetString(entry.Value),(long)entry.Key.Timestamp);
}
}
client.closeScanner(scanId);
client.Dispose();
transport.Close();
}catch (Exception e)
{
Console.WriteLine(e);
}
//}}
}
}
}
Adding Thrift to C# project involves two steps:
Add the C# code that has been generated by means of the Thrift compiler
Build Thrift.DLL and add it as a reference to your project. Alternatively, it is possible to link the code into your project, however not recommended.
The C# code for step 1 is generated from a Thrift IDL file, which is typically part of the project. In your case, the IDL files are located under proxy/src/main/thrift in the Accumulo tree.
The Thrift compiler and library can be downloaded from http://thrift.apache.org. Note that some projects are using a older version of Apache Thrift, which is not necessarily the latest stable. As elserj mentioned in the comments, Accumulo 1.4.x depends on Thrift 0.6.1, Accumulo 1.5.x and greater depend on Thrift 0.9.0.

Categories