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)
- in above link, you will download Visual Studio Community edition 2015 (the main IDE) and Visual Studio Code (a free and small cross-platform portable code editor)
- 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#
- check MS official tutorial page: https://msdn.microsoft.com/en-us/library/dd492171.aspx
- 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
- for gui app, cd to exe location
macpack -m:cocoa -o:./App -n AppName -a:AppName.exe
- distribute, for other people, probably they need install mono on mac, for gtk# ui, also need gtk# lib
- for windows, since mono compatible with .NET, so mostly can directly run
- mono app is small like few kb.
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
- write your cs with gtk lib, save as cs file
- compile with
mcs -pkg:gtk-sharp-2.0 AppName.cs AppNameExtra.cs
- you get a exe
mono AppName.exe
- ref:
method: launch script
- 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"
method: mac app auto build script
- 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.
- Good news is, windows mostly likely have a certain version of .NET framework pre-installed, here is the list
-
- like, win7 = v3.5 .NET; win8 = v4.5 .NET; win10 = v4.6 .NET; xp = v1.0 .NET
-
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 |
- if you use Gtk# ui, you also need to install gtk# (so basically .NET + GTK# make all those exe run fine)
- (GTK# for .NET: Installer for running Gtk#-based applications on Microsoft .NET:)
- 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:
- VS 2019 code complain C# version 7.3 cant support certain thing, use C# ver 9. But your right click on your Project Name > Property : (right side) Build tab - Advanced button > Language version (it says “Automatically selected based on framework version”)
- Solution: go your project folder, edit .csproj file, add following code
<PropertyGroup> <LangVersion>latest</LangVersion> </PropertyGroup>
- ref:
.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)
C# Cross platform UI options
- ref:
- 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
- avalonia ui
- cross-platform .NET UI framework in xaml
- 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())); } } }