[[:improve]] CSharp oder C#. Siehe auch [[coding:c|C]], [[coding:cpp|C++]], [[dotnet|.NET]] oder [[coding::powershell|powershell]] [[http://www.charlespetzold.com/books.html|This guy]] has awesome books. {{::dotnetbook_petzold.pdf}} {{::reverse_csharp.pdf}} [[https://github.com/icsharpcode/ILSpy|ILSpy]], [[https://github.com/dnSpy/dnSpy|DNSpy]] =====Klassen===== using System; namespace HelloWorld { class Hello { #region Main Region static void Main(string[] args) { Console.WriteLine("Parameter: " + args[0]); } #endregion } } C:\Windows\Microsoft.Net\Framework64\v3.5\csc.exe /target:exe /out:HelloWorld.exe HelloWorld.cs https://benohead.com/blog/2014/08/13/three-options-to-dynamically-execute-csharp-code/ =====Threads===== Die Thread-Klasse aus dem System.Threading Namespace ermöglicht die Erstellung und Steuerung von Threads. using System; using System.Threading; namespace ThreadExample { public class Program { static void Main() { Thread thread = new Thread(DoWork); thread.Start(); // Thread starten // Hauptthread setzt seine Arbeit fort for (int i = 0; i < 5; i++) { Console.WriteLine("Main Thread: " + i); Thread.Sleep(1000); } } static void DoWork() { for (int i = 0; i < 5; i++) { Console.WriteLine("Worker Thread: " + i); Thread.Sleep(1000); } } } } Die Task Parallel Library ist eine leistungsfähigere und modernere Methode zur Verwaltung von Threads in C#. Sie bietet eine höhere Abstraktionsebene und erweiterte Funktionen für die parallele Verarbeitung. using System; using System.Threading.Tasks; namespace ThreadExample { public class Program { static void Main() { Task task = Task.Run(DoWork); // Hauptthread setzt seine Arbeit fort for (int i = 0; i < 5; i++) { Console.WriteLine("Main Thread: " + i); Task.Delay(1000).Wait(); } task.Wait(); // Warten, bis der Task abgeschlossen ist } static void DoWork() { for (int i = 0; i < 5; i++) { Console.WriteLine("Worker Thread: " + i); Task.Delay(1000).Wait(); } } } } =====WinForm===== using System; using System.Windows.Forms; namespace WinFormsExample { public class Program : Form { private Button button; public Program() { button = new Button(); button.Text = "Click me!"; button.Click += Button_Click; Controls.Add(button); } private void Button_Click(object sender, EventArgs e) { MessageBox.Show("Button clicked!"); } [STAThread] public static void Main() { Application.Run(new Program()); } } } Winform in Console Application - https://www.youtube.com/watch?v=FJ76vL_EwXA ====Layouts==== In C# gibt es sogenannte Layout-Manager, die ähnlich wie in Java zur dynamischen Platzierung und Anordnung von Steuerelementen in Windows Forms-Anwendungen verwendet werden können. Die Layout-Manager in C# werden als "Layout Controls" bezeichnet. * FlowLayoutPanel: Dieser Layout-Manager platziert die Steuerelemente in einer horizontalen oder vertikalen Anordnung und passt die Größe der Steuerelemente entsprechend an. Wenn der verfügbare Platz nicht ausreicht, werden die Steuerelemente automatisch auf eine neue Zeile oder Spalte umgebrochen. * TableLayoutPanel: Dieser Layout-Manager organisiert die Steuerelemente in einem tabellenartigen Raster mit festgelegten Zeilen und Spalten. Jedes Steuerelement wird in eine bestimmte Zelle des Rasters platziert, wodurch die Positionierung und Größenanpassung der Steuerelemente präzise gesteuert werden kann. * GroupBox: Dies ist kein spezifischer Layout-Manager, sondern ein Container-Steuerelement, das andere Steuerelemente gruppieren kann. Es bietet eine visuelle Trennung und Organisation von Steuerelementen innerhalb eines Rahmens. ===FlowLayout=== using System; using System.Windows.Forms; namespace LayoutExample { public class Program : Form { public Program() { FlowLayoutPanel flowLayoutPanel = new FlowLayoutPanel(); flowLayoutPanel.Dock = DockStyle.Fill; // Füllt den verfügbaren Platz im Formular aus Button button1 = new Button(); button1.Text = "Button 1"; flowLayoutPanel.Controls.Add(button1); Button button2 = new Button(); button2.Text = "Button 2"; flowLayoutPanel.Controls.Add(button2); Button button3 = new Button(); button3.Text = "Button 3"; flowLayoutPanel.Controls.Add(button3); Controls.Add(flowLayoutPanel); } [STAThread] public static void Main() { Application.Run(new Program()); } } } ===TableLayout=== using System; using System.Windows.Forms; namespace LayoutExample { public class Program : Form { public Program() { TableLayoutPanel tableLayoutPanel = new TableLayoutPanel(); tableLayoutPanel.Dock = DockStyle.Fill; // Füllt den verfügbaren Platz im Formular aus tableLayoutPanel.ColumnCount = 2; tableLayoutPanel.RowCount = 2; Button button1 = new Button(); button1.Text = "Button 1"; tableLayoutPanel.Controls.Add(button1, 0, 0); Button button2 = new Button(); button2.Text = "Button 2"; tableLayoutPanel.Controls.Add(button2, 1, 0); Button button3 = new Button(); button3.Text = "Button 3"; tableLayoutPanel.Controls.Add(button3, 0, 1); Button button4 = new Button(); button4.Text = "Button 4"; tableLayoutPanel.Controls.Add(button4, 1, 1); Controls.Add(tableLayoutPanel); } [STAThread] public static void Main() { Application.Run(new Program()); } } } ===GroupBoxLayout=== using System; using System.Windows.Forms; namespace LayoutExample { public class Program : Form { public Program() { GroupBox groupBox = new GroupBox(); groupBox.Text = "Group Box"; groupBox.Dock = DockStyle.Fill; // Füllt den verfügbaren Platz im Formular aus Button button1 = new Button(); button1.Text = "Button 1"; button1.Location = new System.Drawing.Point(10, 20); groupBox.Controls.Add(button1); Button button2 = new Button(); button2.Text = "Button 2"; button2.Location = new System.Drawing.Point(10, 60); groupBox.Controls.Add(button2); Controls.Add(groupBox); } [STAThread] public static void Main() { Application.Run(new Program()); } } } =====Pointer===== Auch in C# gibt es sogenannte Zeiger (Pointer), allerdings sind sie auf spezielle Kontexte beschränkt und der direkte Zugriff auf den Speicher über Zeiger ist in C# stark eingeschränkt und nur in sogenannten "unsafe" Codeblöcken erlaubt. unsafe class Program { static void Main(string[] args) { int number = 10; int* p = &number; // Zeiger auf die Variable 'number' erstellen Console.WriteLine(*p); // Ausgabe: 10 (Wert über den Zeiger dereferenzieren) *p = 20; // Wert über den Zeiger ändern Console.WriteLine(number); // Ausgabe: 20 (Änderung des Werts über den Zeiger) Console.ReadLine(); } } =====Datenstrukturen===== ====Array==== int[] numbers = new int[5]; // Deklaration und Initialisierung eines Integer-Arrays mit einer Größe von 5 numbers[0] = 1; // Wertzuweisung an das erste Element numbers[1] = 2; numbers[2] = 3; numbers[3] = 4; numbers[4] = 5; Console.WriteLine(numbers[2]); // Ausgabe: 3 (Zugriff auf das dritte Element) ====List==== List fruits = new List(); // Deklaration einer generischen Liste von Zeichenketten fruits.Add("Apple"); // Elemente hinzufügen fruits.Add("Banana"); fruits.Add("Orange"); Console.WriteLine(fruits.Count); // Ausgabe: 3 (Anzahl der Elemente in der Liste) fruits.Remove("Banana"); // Element entfernen foreach (string fruit in fruits) { Console.WriteLine(fruit); // Ausgabe: Apple, Orange (Durchlaufen der Liste) } ====Stack==== Stack stack = new Stack(); // Deklaration eines generischen Stapels von Ganzzahlen stack.Push(1); // Elemente auf den Stapel legen stack.Push(2); stack.Push(3); Console.WriteLine(stack.Pop()); // Ausgabe: 3 (Entfernen des obersten Elements) ====Queue==== Queue queue = new Queue(); // Deklaration einer generischen Warteschlange von Zeichenketten queue.Enqueue("John"); // Elemente in die Warteschlange einfügen queue.Enqueue("Jane"); queue.Enqueue("Mike"); Console.WriteLine(queue.Dequeue()); // Ausgabe: John (Entfernen des ersten Elements) ====Linked List==== LinkedList linkedList = new LinkedList(); // Deklaration einer generischen verknüpften Liste von Ganzzahlen linkedList.AddLast(1); // Elemente am Ende der Liste hinzufügen linkedList.AddLast(2); linkedList.AddLast(3); LinkedListNode node = linkedList.Find(2); // Suchen nach einem Knoten mit Wert 2 linkedList.AddAfter(node, 4); // Element nach dem gefundenen Knoten einfügen foreach (int num in linkedList) { Console.WriteLine(num); // Ausgabe: 1, 2, 4, 3 (Durchlaufen der Liste) } ====Dictionary==== Dictionary dictionary = new Dictionary(); // Deklaration eines generischen Wörterbuchs mit Zeichenketten als Schlüssel und Ganzzahlen als Werte dictionary.Add("Apple", 10); // Schlüssel-Wert-Paare hinzufügen dictionary.Add("Banana", 5); dictionary.Add("Orange", 3); Console.WriteLine(dictionary["Banana"]); // Ausgabe: 5 (Zugriff auf den Wert mit dem Schlüssel "Banana") dictionary["Apple"] = 15; // Wert aktualisieren foreach (KeyValuePair pair in dictionary) { Console.WriteLine(pair.Key + ": " + pair.Value); // Ausgabe: Apple: 15, Banana: } ====Set==== HashSet set = new HashSet(); // Deklaration eines Hashsets von Zeichenketten set.Add("Apple"); // Elemente hinzufügen set.Add("Banana"); set.Add("Orange"); set.Add("Apple"); // Duplikate werden automatisch entfernt Console.WriteLine(set.Count); // Ausgabe: 3 (Anzahl der eindeutigen Elemente im Set) set.Remove("Banana"); // Element entfernen foreach (string item in set) { Console.WriteLine(item); // Ausgabe: Apple, Orange (Durchlaufen des Sets) } =====Singleton===== using System; namespace Test { public class Program { public static void Main(string[] args) { // Constructor is protected -- cannot use new Singleton s1 = Singleton.Instance(); Singleton s2 = Singleton.Instance(); // Test for same instance if (s1 == s2) { Console.WriteLine("Objects are the same instance"); } } } public class Singleton { static Singleton instance; // Constructor is 'protected' protected Singleton() { } /* public static Singleton Instance(string str) { if (instance == null) { instance = new Singleton(); } return instance; } */ /* // not thread safe public static Singleton Instance { get { if (instance == null) { instance = new Singleton(); } return instance; } } */ /* // thread safe private static readonly object padlock = new object(); public static Singleton Instance { get { lock (padlock) { if (instance == null) { instance = new Singleton(); } return instance; } } } */ } } =====Generic Types===== using System; using System.Collections.Generic; namespace GenericApp { public class TestClass { // define an Array of Generic type with length 5 T[] obj = new T[5]; int count = 0; public void Add(T item) { if (count + 1 < 6) { obj[count] = item; } count++; } //indexer for foreach statement iteration public T this[int index] { get { return obj[index]; } set { obj[index] = value; } } } class Program { static void Main(string[] args) { //instantiate generic with Integer TestClass intObj = new TestClass(); intObj.Add(1); intObj.Add(2); intObj.Add(3); intObj.Add(4); intObj.Add(5); //displaying values for (int i = 0; i < 5; i++) { Console.WriteLine(intObj[i]); //No unboxing } } } } =====COM InterOp===== using System; using System.Runtime.InteropServices; [ComVisible(true)] [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] [Guid("E0F805D1-77CC-4C14-930E-5D65A1A39A2F")] public interface IMyComInterface { void SayHello(string name); } [ComVisible(true)] [ClassInterface(ClassInterfaceType.None)] [Guid("1C9D8F2B-8D52-45A7-9E3D-ED6F2CE010E0")] public class MyComClass : IMyComInterface { public void SayHello(string name) { Console.WriteLine($"Hello, {name}!"); } } Für InterOp registrieren (systemweit) C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regasm.exe /codebase /tlb ClassLibrary.dll $comObject = New-Object -ComObject "MyComClass" $comObject.SayHello("World") =====Server-Client===== using System; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Net; using System.Net.Sockets; namespace ConsoleServer { public enum MessageType { String, Int, Float, Vector } [Serializable] public struct Vector3 { public float X { get; set; } public float Y { get; set; } public float Z { get; set; } public Vector3(float x, float y, float z) { X = x; Y = y; Z = z; } } [Serializable] public class Message { public MessageType Type { get; set; } public string Content { get; set; } public int IntValue { get; set; } public float FloatValue { get; set; } public Vector3 VectorValue { get; set; } public Message(MessageType type, string content = "", int intValue = 0, float floatValue = 0.0f, Vector3 vectorValue = default(Vector3)) { Type = type; Content = content; IntValue = intValue; FloatValue = floatValue; VectorValue = vectorValue; } public byte[] ToBytes() { using (MemoryStream stream = new MemoryStream()) { BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, this); return stream.ToArray(); } } public static Message FromBytes(byte[] data) { using (MemoryStream stream = new MemoryStream(data)) { BinaryFormatter formatter = new BinaryFormatter(); return (Message)formatter.Deserialize(stream); } } } public class Peer { private TcpClient client; public Peer(TcpClient _client) { client = _client; } public TcpClient Client { get { return client; } } } public class MultiplayerServer { private TcpListener tcpListener; private Thread listenerThread; private List peers = new List(); public MultiplayerServer() { this.tcpListener = new TcpListener(IPAddress.Any, 5555); this.listenerThread = new Thread(new ThreadStart(ListenForClients)); this.listenerThread.Start(); } private void ListenForClients() { this.tcpListener.Start(); while (true) { TcpClient client = this.tcpListener.AcceptTcpClient(); Peer peer = new Peer(client); peers.Add(peer); Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm)); clientThread.Start(peer); } } private void HandleClientComm(object _peer) { Peer peer = (Peer)_peer; TcpClient tcpClient = peer.Client; NetworkStream clientStream = peer.Client.GetStream(); byte[] messageBuffer = new byte[4096]; int bytesRead; while (true) { bytesRead = 0; try { bytesRead = clientStream.Read(messageBuffer, 0, 4096); } catch { break; } if (bytesRead == 0) break; Message receivedMessage = Message.FromBytes(messageBuffer); //Console.WriteLine("Received message from client: " + receivedMessage.Content); // Fire the MessageReceived Event MessageReceived(receivedMessage, peer); // response /* Message responseMessage = new Message(MessageType.String, "Server has received your message: " + receivedMessage.Content); SendMessageToClient(tcpClient, responseMessage); SendMessageToAllClients(responseMessage); */ } peers.Remove(peer); tcpClient.Close(); } public void SendMessageToClient(Peer peer, Message message) { NetworkStream clientStream = peer.Client.GetStream(); byte[] messageBytes = message.ToBytes(); clientStream.Write(messageBytes, 0, messageBytes.Length); } public void SendMessageToAllClients(Message message) { byte[] messageBytes = message.ToBytes(); //foreach (TcpClient client in connectedClients) foreach(Peer peer in peers) { NetworkStream clientStream = peer.Client.GetStream(); clientStream.Write(messageBytes, 0, messageBytes.Length); } } public void StartListening() { // Implement your game logic here for the server } protected virtual void OnMessageReceived(Message message, Peer peer) { MessageReceived?.Invoke(message, peer); } public event Action MessageReceived; } public class MultiplayerClient { private TcpClient tcpClient; private Thread clientThread; private NetworkStream clientStream; public MultiplayerClient() { this.tcpClient = new TcpClient(); this.clientThread = new Thread(new ThreadStart(ConnectToServer)); this.clientThread.Start(); } private void ConnectToServer() { this.tcpClient.Connect("127.0.0.1", 5555); this.clientStream = this.tcpClient.GetStream(); byte[] serverResponseBuffer = new byte[4096]; int bytesRead; while (true) { bytesRead = 0; try { bytesRead = this.clientStream.Read(serverResponseBuffer, 0, 4096); } catch { break; } if (bytesRead == 0) break; Message serverResponse = Message.FromBytes(serverResponseBuffer); OnMessageReceived(serverResponse); } } protected virtual void OnMessageReceived(Message message) { MessageReceived?.Invoke(message); } public event Action MessageReceived; // Methode zum Senden von Nachrichten an den Server public void SendMessageToServer(Message message) { byte[] messageBytes = message.ToBytes(); this.clientStream.Write(messageBytes, 0, messageBytes.Length); } } public class Game { private MultiplayerClient client; private MultiplayerServer server; private bool isClient, isServer = false; public Game() { Console.WriteLine("Choose your role: [1] Server / [2] Client"); string roleChoice = Console.ReadLine(); if (roleChoice == "1") { server = new MultiplayerServer(); server.StartListening(); server.MessageReceived += OnServerMessageReceived; isServer = true; } else if (roleChoice == "2") { client = new MultiplayerClient(); client.MessageReceived += OnMessageReceived; isClient = true; } else { Console.WriteLine("Invalid input. Exiting the program."); } } private void OnMessageReceived(Message message) { Console.WriteLine("[client] Received message from server: " + message.Content); } private void OnServerMessageReceived(Message message, Peer peer) { Console.WriteLine("[server] Received message from server: " + message.Content); server.SendMessageToAllClients(message); server.SendMessageToClient(peer, message); } public void Run() { if (isClient) { string msg; while (true) { msg = Console.ReadLine(); client.SendMessageToServer(new Message(MessageType.String, msg)); } } } public static void Main() { Game game = new Game(); game.Run(); } } } =====Sprite Animation===== using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System; using System.Drawing; using System.Windows.Forms; namespace AnimationPlayer { public class SpriteAnimation { private PictureBox pictureBox1; private Image spriteSheet; private int frameWidth; private int frameHeight; private int currentFrame; private int totalFrames; private int currentAnimation; public SpriteAnimation(PictureBox pictureBox, Image spriteSheet, int frameWidth, int frameHeight, int totalFrames, int _currentAnimation) { this.pictureBox1 = pictureBox; this.spriteSheet = spriteSheet; this.frameWidth = frameWidth; this.frameHeight = frameHeight; this.totalFrames = totalFrames; this.currentAnimation = _currentAnimation; // Setzen Sie die Größe des PictureBox-Steuerelements auf die Größe eines Frames. pictureBox.Size = new Size(frameWidth, frameHeight); // Event-Handler für das Paint-Ereignis hinzufügen, um die Animation zu zeichnen. pictureBox.Paint += PictureBox_Paint; } private void PictureBox_Paint(object sender, PaintEventArgs e) { // Berechnen Sie die Quell- und Zielrechtecke für das aktuelle Frame. Rectangle sourceRect = new Rectangle(currentFrame * frameWidth, currentAnimation * frameHeight, frameWidth, frameHeight); Rectangle destRect = new Rectangle(0, 0, frameWidth, frameHeight); // Zeichnen Sie das aktuelle Frame auf das PictureBox-Steuerelement. e.Graphics.DrawImage(spriteSheet, destRect, sourceRect, GraphicsUnit.Pixel); } public void StartAnimation() { // Erstellen Sie einen Timer, um die Animation zu steuern. Timer timer = new Timer(); timer.Interval = 120; // Passen Sie die Intervallzeit an Ihre Anforderungen an. timer.Tick += Timer_Tick; timer.Start(); } private void Timer_Tick(object sender, EventArgs e) { // Aktualisieren Sie das aktuelle Frame und zeichnen Sie die Animation erneut. currentFrame = (currentFrame + 1) % totalFrames; pictureBox1.Invalidate(); // Ruft das Paint-Ereignis auf. if (!pictureBox1.Visible) pictureBox1.Visible = true; } public void ChangeAnimation(int newFrameWidth, int newFrameHeight, int newTotalFrames, int newAnimation) { // Ändern Sie die Animationseinstellungen. frameWidth = newFrameWidth; frameHeight = newFrameHeight; totalFrames = newTotalFrames; currentAnimation = newAnimation; // Setzen Sie die Größe des PictureBox-Steuerelements auf die Größe eines Frames. pictureBox1.Size = new Size(frameWidth, frameHeight); // Setzen Sie das aktuelle Frame auf den Anfang. currentFrame = 0; // Zeichnen Sie die Animation neu. pictureBox1.Invalidate(); } } public partial class Form1 : Form { public Form1() { InitializeComponent(); PictureBox pictureBox1 = new PictureBox(); pictureBox1.Width = 256; pictureBox1.Height = 384; pictureBox1.Visible = true; pictureBox1.Location = new Point(10, 10); Controls.Add(pictureBox1); PictureBox pictureBox2 = new PictureBox(); pictureBox2.Width = 256; pictureBox2.Height = 384; pictureBox2.Visible = true; pictureBox2.Location = new Point(100, 100); Controls.Add(pictureBox2); PictureBox pictureBox3 = new PictureBox(); pictureBox3.Width = 256; pictureBox3.Height = 384; pictureBox3.Visible = true; pictureBox3.Location = new Point(200, 200); Controls.Add(pictureBox3); PictureBox pictureBox4 = new PictureBox(); pictureBox4.Width = 256; pictureBox4.Height = 384; pictureBox4.Visible = true; pictureBox4.Location = new Point(300, 300); Controls.Add(pictureBox4); // Laden Sie Ihr Spritesheet-Bild und passen Sie die Parameter an. Image spriteSheet = Image.FromFile("C:\\Users\\manuel\\Desktop\\EasyScript_RPG_Cutscene_Demo_Source\\Demo\\Resources\\NPC01.png"); int frameWidth = 64; // Breite eines Frames in Pixeln int frameHeight = 96; // Höhe eines Frames in Pixeln int totalFrames = 4; // Gesamtanzahl der Frames in einer Spalte // Erstellen Sie eine Instanz der SpriteAnimation-Klasse. SpriteAnimation spriteAnimation1 = new SpriteAnimation(pictureBox1, spriteSheet, frameWidth, frameHeight, totalFrames, 0); // Starten Sie die Animation. spriteAnimation1.StartAnimation(); for(int i = 0; i < 99999999; ) { int t = (int)(Math.PI + i / Math.E); i++; } SpriteAnimation spriteAnimation2 = new SpriteAnimation(pictureBox2, spriteSheet, frameWidth, frameHeight, totalFrames, 1); // Starten Sie die Animation. spriteAnimation2.StartAnimation(); for (int i = 0; i < 99999999;) { int t = (int)(Math.PI + i / Math.E); i++; } SpriteAnimation spriteAnimation3 = new SpriteAnimation(pictureBox3, spriteSheet, frameWidth, frameHeight, totalFrames, 2); // Starten Sie die Animation. spriteAnimation3.StartAnimation(); for (int i = 0; i < 99999999;) { int t = (int)(Math.PI + i / Math.E); i++; } SpriteAnimation spriteAnimation4 = new SpriteAnimation(pictureBox4, spriteSheet, frameWidth, frameHeight, totalFrames, 3); // Starten Sie die Animation. spriteAnimation4.StartAnimation(); } } }