Tangible Software Solutions

C# and Python Comparison and Equivalents


Equivalents were produced with the Free Edition of C# to Python Converter.


The closest thing in Python to an abstract method is an empty method:

C# Python
public abstract class AbstractClass
{
    public abstract void abstractMethod();
}
class AbstractClass:
    def abstractMethod(self):
        pass

You can convert C# arrays to Python's 'list'.

Unsized Array

C# Python
int[] myArray; myArray = []

Sized Array

C# Python
int[] myArray = new int[2]; myArray = [0 for _ in range(2)]

Access Array Element

C# Python
x = myArray[0]; x = myArray[0]   # no change

Jagged Array

C# Python
float[][] myArray = new float[][] { new float[] {x, y}}; myArray = [[x, y]]

Rectangular Array

C# Python
int[][] myArray = new int[][] {
    new int[] {10, 20, 30 ,40},
    new int[] {50, 60, 70, 80, 90, 100},
    new int[] {110, 120}
};
myArray = [[10, 20, 30, 40], [50, 60, 70, 80, 90, 100], [110, 120]]

C# requires statements to end with semi-colons and multi-statement blocks to be enclosed in braces, while Python only requires indentation to correspond to the logical block levels and block headers to end in colons. The current instance is only available within instance methods via the first parameter of the method, usually named 'self' by convention (static methods are distinguished by the @staticmethod decorator).

C# Python
class FooClass
{
    void instanceMethod()
    {
        if (fooCondition)
        {
            fooLogicOne();
            fooLogicTwo();
        }
    }
}
class FooClass:
    def instanceMethod(self):
        if fooCondition:
            fooLogicOne()
            fooLogicTwo()
C# Python
void casts()
{
    x = (int)y;
    x = (float)y;
    x = (string)y;
}
def casts(self):
    x = int(y)
    x = float(y)
    x = str(y)

Lists

C#'s System.Collections.Generic.List collection and Python's 'list' are very close equivalents.

C# Python
void Lists()
{
    List<int> myList = new List<int>();
    myList.Add(1);
    myList.Insert(1, 2);
    int i = 1;
    myList[0] = i;
    i = myList[0];
}
def arrayLists(self):
    myList = []
    myList.append(1)
    myList.insert(1, 2)
    i = 1
    myList[0] = i
    i = myList[0]

Dictionaries

C#'s System.Collections.Generic.Dictionary collection and Python's 'dict' are very close equivalents.

C# Python
void Dictionaries()
{
    Dictionary<string, int> map = new Dictionary<string, int>();
    string s = "test";
    map[s] = 1;
    int i = map[s];
    i = map.Count;
    bool b = map.Count == 0;
    map.Remove(s);
}
def hashMaps(self):
    map = {}
    s = "test"
    map[s] = 1
    i = map[s]
    i = len(map)
    b = not map
    map.pop(s)

Python has a single comment format, starting with the '#' symbol. Multiline comments can also be created using triple quoted multiline strings.

C# Python
// single-line comment

foo(); // end-of-line comment

/* comment
over multiple lines
*/
# single-line comment

foo() # end-of-line comment

# comment
# over multiple lines
#

# using multiline strings to simulate multiline comments:
"""
comment
over multiple lines
"""

Local Variable

C# Python
int myVar = 2; myVar = 2  # Python infers the type

Inferred Types

Inferred typing is available in C#, but Python always infers the type:

C# Python
var myVar = 2; myVar = 2

Static Field

In Python, static fields are initialized at the class level:

C# Python
class FooClass
{
    public static int staticField = 7;
}
class FooClass:
    staticField = 7

Instance Field

In Python, instance fields are not listed at the class level and are qualified with the instance object, given by the first instance method parameter (usually named 'self' by convention):

C# Python
class FooClass
{
    public int instanceField = 2;
}
class FooClass:
    def __init__(self):
        self.instanceField = 2

Local Constant

C# Python
const int myConst = 2; MY_CONST = 2  # at method level — up to programmers to respect the naming convention and avoid changing it

Class Constant

C# Python
public const int myConst = 2; MY_CONST = 2  # at class level — up to programmers to respect the naming convention and avoid changing it

Python constructors are named __init__, but a serious shortcoming of Python is the restriction of allowing only one constructor per class.

C# Python
class Foo
{
    public Foo()
    {
    }
}
class Foo:
    def __init__(self):
        pass

Python and C# both allow default or optional parameters.

C# Python
public void defaultParam(int param = 0)
{
    ...
}
def defaultParam(self, param=0):
    ...

Since methods are first class objects in Python delegates are converted easily:

C# Python
public class Test
{
    public delegate void FooDelegate(int arg);

    public static void static_method(int p) {
        Console.WriteLine("static_method called with arg " + p);
    }

    public void instance_method(int p) {
        Console.WriteLine("instance_method called with arg " + p);
    }

    public void method() {
        FooDelegate f1 = new FooDelegate(static_method);
        f1(1);

        FooDelegate f2 = instance_method;
        f2(2);

        FooDelegate f3 = (int i) => instance_method(i);
        f3(3);
    }
}
class Test:
    class FooDelegate:
        def __init__(self, method, instance):
            self._method = method
            self._instance = instance

        def invoke(self, arg):
            if self._instance is None:
                self._method(arg)
            else:
                self._method(self._instance, arg)

    @staticmethod
    def static_method(p):
        print("static_method called with arg " + str(p))

    def instance_method(self, p):
        print("instance_method called with arg " + str(p))

    def method(self):
        f1 = Test.FooDelegate(Test.static_method, None)
        f1.invoke(1)

        f2 = Test.FooDelegate(Test.instance_method, self)
        f2.invoke(2)

        f3 = Test.FooDelegate(lambda i : self.instance_method(i), None)
        f3.invoke(3)

Enums in C# have equivalents in Python using the 'enum' module:

C# Python
public enum Simple
{
    Foo,
    Bar
}
from enum import Enum

class Simple(Enum):
    FOO = 0
    BAR = 1

......

C# Python
// value equality with primitives:
int i = 1;
int j = 1;
bool valuesIdentical = i == j;

// identity equality with class types:
Foo f = new Foo();
Foo g = f;
bool objectsIdentical = f == g;

// strings:
string s1 = "abc";
string s2 = s1;
valuesIdentical = s1 == s2;
// caution: C# string internment often
// makes this true whenever '==' is true:
objectsIdentical = string.ReferenceEquals(s1, s2);
# value equality:
i = 1
j = 1
valuesIdentical = i == j

# identity equality
f = Foo()
g = f
objectsIdentical = f is g

# strings:
s1 = "abc"
s2 = s1
valuesIdentical = s1 == s2
# caution: Python string internment often
# makes this true whenever '==' is true:
objectsIdentical = s1 is s2

The Python try/except/finally scheme is equivalent to C#'s try/catch/finally:

C# Python
void exceptionHandling()
{
    try
    {
    }
    catch (Foo f)
    {
        throw f;
    }
    catch (Bar)
    {
        throw new Bar();
    }
    finally
    {
    }
}
def exceptionHandling(self):
    try:
        pass
    except Foo as f:
        raise f
    except Bar:
        raise Bar()
    finally:
        pass

Python doesn't have extension methods, so a C# extension method is just converted to an ordinary Python static method (calls to the method have to be adjusted to static calls using the class name).

C# Python
public static class ContainsExtension
{
    public static void ExtensionMethod(this string myParam)
    {
        // ...
    }
}

class TestClass
{
    void TestMethod()
    {
        string s = "abc";
        s.ExtensionMethod();
    }
}
class ContainsExtension:
    @staticmethod
    def ExtensionMethod(myParam):
        # ...
        pass

class TestClass:
    def _TestMethod(self):
        s = "abc"
        ContainsExtension.ExtensionMethod(s)
C# Python
if (conditionA)
{
}
else if (conditionB)
{
}
else
{
}
if conditionA:
    pass
elif conditionB:
    pass
else:
    pass

C# allows incrementing and decrementing integers within expressions, while Python doesn't. The following shows how C# to Python Converter handles some cases.

C# Python
public void incrementDecrement()
{
    i = ++j;

    i = j++;

    i = j--;

    i = s + --t;

    i = s + t--;

    i = s + ++t;

    i = s + t++;
}
def incrementDecrement(self):
    j += 1
    i = j

    i = j
    j += 1

    i = j
    j -= 1

    t -= 1
    i = s + t

    i = s + t
    t -= 1

    t += 1
    i = s + t

    i = s + t
    t += 1

Python does not have indexers, so you must use get/set methods instead:

C# Python
public int this[int index]
{
    get
    {
        return field[index];
    }
    set
    {
        field[index] = value;
    }
}
def get(self, index):
    return field[index]
def set(self, index, value):
    field[index] = value
C# Python
public class one
{
    protected int baseField = 1;

    public one(int i)
    {
    }

    public virtual void baseMethod()
    {
    }
}

public class two : one
{
    public two() : base(0)
    {
    }

    public void method()
    {
        base.baseField = 2;
        base.baseMethod();
    }
}
class one:

    def __init__(self, i):
        self.baseField = 1

    def baseMethod(self):
        pass

class two(one):
    def __init__(self):
        super().__init__(0)

    def method(self):  
        self.baseField = 2
        super().baseMethod()

Defining Interfaces

Interfaces in Python are just classes with empty methods:

C# Python
public interface IFooInterface
{
    void method();
}
class IFooInterface:
    def method(self):
        pass

Implementing Interfaces

C# Python
public class Foo : IFooInterface
{
    public void method()
    {
        ... some code
    }
}
class Foo(IFooInterface):
    def method(self):
        ... some code

Expression Lambda

C# Python
myVar = (String text) => text.Length; myVar = lambda text : len(text)

Multi-statement Lambda

C# Python
myVar = (Foo param1, Bar param2) =>
{
    // ...multiple statements
}
No direct Python equivalent
C# Python
x = y && z;
x = y || z;
x = !y;
i = j | k;
i = j & k;
i = j ^ k;
x = y and z
x = y or z
x = not y
i = j | k
i = j & k
i = j ^ k
C# Python
// while loop:
while (while_condition)
{
    foo();

    // break and continue:
    if (b)
        break;
    else
        continue;
}

// do-while loop:
do
{
    foo();
} while (do_condition);

// traditional for loop:
for (int i = 0; i < 10; i++)
{
    foo();
}

// 'for each' loop:
foreach (Foo f in FooList)
{
}
# while loop:
while while_condition:
    foo()

    # break and continue:
    if b:
        break
    else:
        continue

# do-while loop:
# Python doesn't have a do-while loop, so simulate it:
condition = True
while condition:
    foo()
    condition = do_condition

# traditional for loop:
for i in range(0, 10):
    foo()

# 'for each' loop:
for f in FooList:
    pass
C# Python
void exponentiation()
{
    x = Math.Pow(y, z);
}

void integerDivision()
{
    // C# integer division always rounds towards 0:
    int i = -5;
    int j = 2;
    int result = i / j;   // result is -2
}

void modulusOperator()
{
    // C# and Python '%' operators are only equivalent for positive numbers:
    int i = 2;
    int j = -3;
    int result = i % j;   // result is 2
}

void otherMathOperations()
{
    x = Math.Abs(y);

    // see the System.Math class for many more functions:
    x = Math.Cos(y);
    x = Math.E;
    x = Math.PI;
}
import math

def exponentiation(self):
    x = y ** z

def integerDivision(self):
    i = -5
    j = 2
    result = math.trunc(i / float(j))   # result is -2

    # Python integer division rounds away from 0 when negative:
    result = i / j   # result is -3

def modulusOperator(self):
    i = 2
    j = -3
    result = math.fmod(i, j)   # result is 2

    # Python modulus operator produces a different result:
    result = i % j   # result is -1

def otherMathOperations(self):
    x = abs(y)   # 'abs' is a built-in Python function

    # see the Python 'math' module for many more functions:
    x = math.cos(y)
    x = math.e
    x = math.pi

Python instance methods have a first parameter indicating the instance ('self' is the convention for this parameter and not a keyword), and static methods have the '@staticmethod' decorator.

C# Python
public void instanceMethod()
{
}

public static void staticMethod()
{
}
def instanceMethod(self):
    pass

@staticmethod
def staticMethod():
    pass
C# Python
public class SomeType
{
    private int IntValue = 1;

    public static int operator +(SomeType X, SomeType Y)
    {
        return X.IntValue + Y.IntValue;
    }

    public void OperatorTest()
    {
        SomeType o = new SomeType();
        SomeType p = new SomeType();
        i = o + p;
    }
}
class SomeType:
    def __init__(self):
        # instance fields found by C# to Python Converter:
        self._IntValue = 1

    @staticmethod
    def op_add(X, Y):
        return X._IntValue + Y._IntValue

    def OperatorTest(self):
        o = SomeType()
        p = SomeType()
        i = SomeType.op_add(o, p)
C# Python
void method(params string[] args)
{
    foreach (string x in args)
    {
        ... logic for each item in args
    }
}
def method(self, *args):
    for x in args:
        ... logic for each item in args

Python does not have properties, so you must use get/set methods instead:

C# Python
public int IntProperty
{
    get
    {
        return intField;
    }
    set
    {
        intField = value;
    }
}
def get_int_property(self):
    return intField
def set_int_property(self, value):
    intField = value

Python does not support C#-style 'ref' parameters. All Python parameters are passed by value (if it's a reference, then the reference is passed by value). However, you can wrap the parameter type in another type (we call it 'RefObject').

Here's a simple example:

C# Python
public void refParamMethod(ref int i)
{
    i = 1;
}

public void callRefParamMethod()
{
    int i = 0;
    refParamMethod(ref i);
}
def refParamMethod(self, i):
    i.arg_value = 1

def callRefParamMethod(self):
    i = 0
    temp_ref_i = RefObject(i)
    self.refParamMethod(temp_ref_i)
    i = temp_ref_i.arg_value

# ----------------------------------------------------------------------------------------
# Copyright © 2022 - 2024 Tangible Software Solutions, Inc.
# This class can be used by anyone provided that the copyright notice remains intact.
#
# This class is used to replicate the ability to have 'ref' parameters in Python.
# ----------------------------------------------------------------------------------------
class RefObject:
    def __init__(self, ref_arg):
        self.arg_value = ref_arg

C# static constructors and Python code at the class level serve the same purpose.

C# Python
class Foo
{
    public static int field;

    static Foo()
    {
        ... logic to set 'field' value
    }
}
class Foo:
    field = 0

    ... logic to set 'field' value
C# Python
String s = initValue;
int i = s.IndexOf(y);
i = s.LastIndexOf(y);
i = s.Length;
bool b = s.Contains(y);
s = s.Substring(i);
s = s.Substring(i, j);
b = s.EndsWith(y);
b = s.StartsWith(y);
s = s.ToLower();
s = s.ToUpper();
s = s.TrimStart();
s = s.TrimEnd();
s = initValue
i = s.find(y)
i = s.rfind(y)
i = len(s)
b = y in s
s = s[i:]
s = s[i:i + j]
b = s.endswith(y)
b = s.startswith(y)
s = s.casefold()
s = s.upper()
s = s.lstrip()
s = s.rstrip()

Python 3.10 has 'match' syntax, but if/elif/else is used prior to Python 3.10.

C# Python
switch (pivot)
{
    case 1:
        foo();
        break;
    case 2:
    case 3:
        bar();
        break;
    case 4:
        break;
    default:
        ack();
        break;
}

Python 3.10:

match pivot:
    case 1:
        foo()
    case 2 | 3:
        bar()
    case 4:
        pass
    case other:
        ack()

Prior to Python 3.10:

if pivot == 1:
    foo()
elif pivot == 2 or pivot == 3:
    bar()
elif pivot == 4:
    pass
else:
    ack()
C# Python
result = condition ? truePart : falsePart; result = truePart if condition else falsePart
C# Python
// checking if 'f' is an instance of type 'Foo':
bool b = f is Foo;
# checking if 'f' is an instance of type 'Foo':
b = isinstance(f, Foo)
C# Python
using FooNamespace;

// type import with alias matching type name:
using FooClass = FooNamespace.FooClass;

// namespace alias:
using fooalias = FooNamespace;

// type import:
using static FooNamespace.BarClass;
from FooNamespace import *

from FooNamespace import FooClass

* no equivalent to type or namespace aliases *

* no equivalent to C# 'using static' *
C# Python
using (FooType foo = new FooType())
{
    ...
}
with FooType() as foo:
    ...
C# Python
// verbatim string:
string s = @"multiline
    verbatim
    string";

// C#11 raw string literal:
string s = """
multiline
    verbatim
    string
""";
s = """multiline
    verbatim
    string"""

Copyright © 2004 – 2024 Tangible Software Solutions, Inc.