devwiki:cs

C# Basic

  • Access modifiers like “public, private” defines accessable range of a function
    • normally, private for inside class method, public for functions will be used by other objects.
    • a function without defined “access modifier” will be as “Internal”
    • public is simple, all accessible
    • private means: only only same class object can access
    • internal (default) means: same class and its inheritance class
    • protected internal: internal + outside derived??
    • protected: ??
using System; // like python, need to import sys,os for some basic function
int i = 1; // like c++, statement needs ends with ;
const int age = 100;
float amount = 1;
float amountDetail = 1.2f; // for . number, you need put f behind;
double noNeedEnd = 1.2; // for double, no need extra, opt with d;
decimal superDetail = 1.2m; // m to indicate deciMal
 
char letter = 'A'; string name = "test"; book isWorking;
var i=1; // like javascript, you can use var for c# to auto detect as int for the value.
 
int[] intArray = {5,2,3}; // fix size array, unlike mixed python intArrayExtra=[5,2,3,'ok']
int[] intEmpty = new int[3]; // 3 slot
Array.Sort(intArray);
foreach (int i in intArray)
{
  Console.WriteLine(i);
}
 
// extra lib
using System.Linq;
Console.WriteLine("max: "+intArray.Max());
Console.WriteLine("min: {0}; sum: {1} ", intArray.Min(), intArray.Sum()); // python .format like print
// python like list, no fix size, need extra lib
using System.Collections.Generic;
List<int> numberList = new List<int>();
numberList.Add(32); // like python append
// write out list as string
Console.WriteLine( string.Join(", ", selected.ToArray() )
 
 
int[] extraArray = {10,11,12};
numberList.AddRange(extraArray); // like python extend
numberList.Insert(0, 100); // insert at index
numberList.Remove(10); // find number 10 and remove 1st instance
numberList.RemoveAt(3); // Remove 3rd item
numberList.Clear(); // empty, like python .clear()
numberList.IndexOf(100); //
numberList.Sort();
numberList.Reverse();
int index = numberList.BinarySearch(100);
 
// python like: stack ; append(56), pop(), use Stack object instead
if(numberList.Any()){
    numberList.RemoveAt(numberList.Count - 1); // no return though
}
// python like: queue; append(56), pop(0), use Queue object instead
numberList.RemoveAt(0); // no return though
 
// however, apart from List, 
// c# has Queue object for Enqueue() and Dequeue(), 
// c# has Stack object for Push() and Pop()
// c# extra: SortedSet, HashSet
  • timestamp to datetime conversion
    using System;
    public DateTime UnixTimeStampToDateTime(double unixTimeStamp)
    {
      // Unix timestamp is seconds past epoch
      DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
      dateTime = dateTime.AddSeconds(unixTimeStamp).ToLocalTime();
      return dateTime;
    }

C# and Visual Studio Community edition

  • if you seriously read this, you probably are free to use Visual Studio Community edition to create any app you like; and mostly probably you will start learning C# (csharp as cs) to create app in it. (it only require you to get the paid professional version once you become big software company, more like feed you up with MS stuffs and you kinda too sticky with it to leave it again)
  • About Visual Studio Community edition, you can download free in this link (4GB download, and take 40GB after install)
  • About C# in visual studio to create apps, technically, you can use C#, VB, C++, F#, Javascript, Python to create apps inside, but most likely, if you plan to use visual studio a lot, C# is the choice to go, since rest language support are mainly to help attracting other developers to use Microsoft visual studio and stick with it.

Get Started in Visual Studio with C#

  • after build your first simple desktop app, you most likely want to change the default app publish info in “AssemblyInfo.cs” (under your top app name in Solution Explorer > Properties > AssemblyInfo.cs), like your app name, company info, copyright info
  • inside the build folder:
    • exe - the 'normal' executable
    • .vshost.exe - a special version of the executable to aid debuging for run app inside visual studio
    • .pdb - the Program Data Base with debug symbols
    • .vshost.exe.manifest - a kind of configuration file containing mostly dependencies on libraries
action shortcut
move line up/dn alt+arrow up/dn
comment cmd+/

Mac and Visual Studio with C#

  • on Mac, with C#, Visual Studio > New Solution : Other > Console App (C#)
  • after it auto generate the sample code, on top bar, click Debug to switch to Release
  • click the top left Start > button to run, you will get a exe file in project folder/bin,
  • to run it on mac directly, go terminal, cd to the directory
    mono AppName.exe
  • (Yes, it is building exe on Mac, and that exe will run fine on windows as well, and on mac, use mono AppName.exe to run on mac, just like “java JavaApp”)
    • also, for GUI, same with Gtk#+C# result on Mac, run with mono
  • to bundle the exe into proper Mac app way. see below

Problem and Solution

  • Problem: visual studio 2019 + mac + gtk# project + compile warning about locale and no Tool panel to add widget
    • Gtk-WARNING **: Locale not supported by C library
  • Solution: write your code in a code editor, and use command-line compile method below,
    • it is visual studio problem, next version may fix.

GTK and Mono compile commandline

  • AppName file with chmod +x to make it launch script, the script will use its name(AppName this case) to launch AppName.exe next to it
    AppName
    #!/bin/sh
    # auto launch Mono App on Mac by ying
    # v0.1 (2022.04.04)
    DIR=$(cd "$(dirname "$0")"; pwd)
    MONO_FRAMEWORK_PATH=/Library/Frameworks/Mono.framework/Versions/Current
    export DYLD_FALLBACK_LIBRARY_PATH="$DIR:$MONO_FRAMEWORK_PATH/lib:/lib:/usr/lib"
    export PATH="$MONO_FRAMEWORK_PATH/bin:$PATH"
     
    exec mono "$DIR/`basename $0`.exe"
  • AppName_build file with chmod +x to make it build script, the script will use its name and _build (AppName_build this case) to pack AppName.exe next to it into a AppName.app mac app
    AppName_build
    #!/bin/sh
    # auto build Mono GTK# App on Mac by ying
    # v0.1 (2022.04.04)
    app_build_name=`basename $0`
    part_list=(${app_build_name//_/ })
    app_name=${part_list[0]}
    echo $app_name
    macpack -m:cocoa -o:./App -n $app_name -a:$app_name.exe

.NET framework install requirement for your C# app

  • since you build your app with C# using .NET framework in visual studio, end user need to have .NET framework installed to be able to use the app, just like people need to have Java Virtual Machine installed for Java written apps.
Target framework version C# version default
.NET 6.x C# 10
.NET 5.x C# 9.0
.NET Core 3.x C# 8.0
.NET Core 2.x C# 7.3
.NET Standard 2.1 C# 8.0
.NET Standard 2.0 C# 7.3
.NET Standard 1.x C# 7.3
.NET Framework all C# 7.3
  • note: no need the mono installer, since if use mono, you need to use mono AppName.exe to run it, with .NET installed, you can direct click exe and run
  • Problem and Solution:
    • BadImageFormatException error
    • Solution: make sure install x86 version of .NET, since most app made are 32bit, not 64bit.

Problem and Solution:

.Net UI frameworks options

Check dotnet version installed

dotnet --list-sdks
  • windows form (since 2001 with .net framework 1.0)
  • WPF (windows presentation foundation, since .net framework 3.0 + directX)
    • ui written in xaml, (extensible application markup language)
    • .net framework 3.0 then ⇒ becomes ⇒ .net core 3.0 and open source (+ self-container, no need linked library)
    • .net framework ends at 4.8 (windows only)
    • .net core goes to 8.0 (2023) [2021 6.0, 2022 7.0] (recommeded for new app)
    • .net core is cross platform (while wpf & windows forms still only run on windows)
  • UWP (Universal Windows Platform since win10)
    • it has WinRT api, (which like Win32)
    • support all other window hardware like xbox
    • run in sandbox, lifecycle management
    • in xaml
  • WinUI (modern native UI platform of Windows)
    • abstract of ui from uwp without win10 as WinUI 2
    • and then WinUI 3.0 (xaml controls + xaml UI frameworks)
    • native UI of windows now,
    • not sandbox and has full access, always run
    • in xaml
    • need install to show in 3rd template dropdown menu (Black App, Packaged WinUI 3 in Desktop)
    • example in : WinUI 3 Controls Gallery
  • Xamarin.Forms (from mobile to all, cross platform)
  • .Net MAUI (open-source and is the evolution of Xamarin, extending to desktop, cross platform)

ref: https://www.youtube.com/watch?v=8NdJaztrNk8

C# Cross platform UI options

  • Info:
    • WPF (since 2006, .net framework 3.0, >= win xp, keyboard mouse input, support c#, xaml ui)
    • UWP (since 2015, win10, opt for touch, support c#, xaml ui)
  • Uno platform:
    • c# + winUI to cross platform
  • cross platform
    • electron shell
    • Xamarin (with different render options)
    • Blazor mobile binding (support browser and web platform)
    • .NET MAUI
Web: 
    > Blazor
Desktop:
    > Cross-Platform:
          -- MAUI
    > Non Cross-Platform:
          --WinUI3
          -- WPF

develop app without using .NET framework

  • as C# is designed by MS to create app with .NET framework, so it make sense to use C# with .NET to create multi-platform apps in the designed workflow
  • For create app without using .NET frame, better creating GUIs in regular C++, Microsoft offers the bare Windows API, MFC, WTL and there are 3rd party products, like Qt or wxWidgets

My Test Code

test.cs
using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Threading.Tasks;
 
namespace TestRun
{
    class MainApp
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hellow World.");
            string reply = Console.ReadLine();
            if (reply != ""){
                Console.WriteLine("Got it:" + reply);
            }
            else{
                Console.WriteLine("nothing");
            }
            int num1 = int.Parse(Console.ReadLine());
            int num2 = int.Parse(Console.ReadLine());
            Console.WriteLine(num1+num2);
            Console.WriteLine(mult(num1,num2));
            reply = Console.ReadLine();
        }
 
        public static float mult(float n1, float n2)
        {
            float result = n1 * n2;
            return result;
        }
    }
}

My App - Output Selected Item in Top Most Explorer in CSharp

Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
/*
ListSelection: (By Shining Ying)
  * v0.1: (2022.05.01) list selected item in top most explorer
 
use with python:
import subprocess
app = r"D:\Projects\Dev\ListSelection\ListSelection\bin\Release\ListSelection.exe"
info=subprocess.Popen( '{0}'.format(app),stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE )
out, err = info.communicate()
result_list = [x.strip() for x in out.split('\n') if x.strip()!='' and not x.strip().startswith('#') ]
 
 */
namespace ListSelection
{
 
    class Program
    {
        // need user32 to use get foreground window
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();
 
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern IntPtr GetTopWindow(IntPtr hWnd);
 
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern bool IsWindowVisible(IntPtr hWnd);
 
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
 
        enum GetWindow_Cmd : uint
        {
            GW_HWNDFIRST = 0,
            GW_HWNDLAST = 1,
            GW_HWNDNEXT = 2,
            GW_HWNDPREV = 3,
            GW_OWNER = 4,
            GW_CHILD = 5,
            GW_ENABLEDPOPUP = 6
        }
 
        // stathread needed to fix unable to cast com object error, as it needs sta thread to use shell object
        // https://stackoverflow.com/questions/31403956/exception-when-using-shell32-to-get-file-extended-properties
        [STAThread]
        static void Main(string[] args)
        {
            List<IntPtr> order_list = new List<IntPtr>();
            /*IntPtr fg_handle = GetForegroundWindow();*/
            IntPtr top_handle = GetTopWindow((IntPtr)null);
            if (top_handle != IntPtr.Zero)
            {
                //Console.WriteLine((int)top_handle);
                if (IsWindowVisible(top_handle))
                {
                    order_list.Add(top_handle);
                }
            }
 
            IntPtr top_next = GetWindow(top_handle, 2);
            while (top_next != IntPtr.Zero) {
                //Console.WriteLine((int)top_next);
                if (IsWindowVisible(top_next)) { 
                    order_list.Add(top_next);
                }
                top_next = GetWindow(top_next, 2);
            }
            /*
            Console.WriteLine("===========================");
            Console.WriteLine("Order:");
            for (int i = 0; i < order_list.Count; i++)
            {
                Console.WriteLine((int)order_list[i]);
            }
            */
 
 
            Shell32.Shell shell = new Shell32.Shell();
            // fix reference: right click project, Add > Reference; in COM, check on Microsoft Shell Controls and Automation
            List<int> win_list = new List<int>();
            foreach (SHDocVw.InternetExplorer window in shell.Windows())
            {
                win_list.Add(window.HWND);
            }
            /*
            Console.WriteLine("===========================");
            Console.WriteLine("win:");
            for (int i = 0; i < win_list.Count; i++)
            {
                Console.WriteLine(win_list[i]);
            }
            */
 
            // top most explorer
            int top_explorer = 0;
            for (int i = 0; i < order_list.Count; i++)
            {
                if (win_list.Contains((int)order_list[i])) {
                    top_explorer = (int)order_list[i];
                    break;
                }
            }
 
            List<string> selected = new List<string>();
            foreach (SHDocVw.InternetExplorer window in shell.Windows())
            {
                // fix SHDocVw: right click project, Add > Reference; in COM, check on Microsoft Internet Controls
                if (window.HWND == top_explorer)
                {
                    Shell32.FolderItems items = ((Shell32.IShellFolderViewDual2)window.Document).SelectedItems();
                    foreach (Shell32.FolderItem item in items)
                    {
                        selected.Add(item.Path);
                        Console.WriteLine(item.Path);
                    }
                }
            }
 
            Console.WriteLine("# By Shining Ying. - 2022/05/01");
            //return (string.Join(", ", selected.ToArray()));
 
        }
    }
}
  • devwiki/cs.txt
  • Last modified: 2022/05/07 06:53
  • by ying