Grokking C# for Python Programmers, Pt. 2


This week, let’s discuss some of the particularities of C# when encountering it for the first time as a Python programmer. We’ll generally assume we are in the context a Unity script, whenever that matters.

Let’s look at some hypothetical C# code:

public class Pineapple : Fruit
{
  public int quantity { get; };
  public string description { get; set; };
  public decimal price { get; };
  private bool expired;
  
  public Pineapple(int startQuantity, string description, int startPrice) 
    {
      this.quantity = startQuantity;
      this.description = description;
      this.price = startPrice;
      this.expired = false;
    }

  public int Eat(int amount) 
    {
      if (quantity >= amount && !expired) 
        {
           quantity -= amount;
           return amount;
        }
      return 0;
    }
}

On first observation, the Python programmer is likely to find the overall appearance of C# code to be quite verbose and a bit boilerplate-y. There’s a few reasons for that. Most obviously, being a C-like language, there’s semicolons just everywhere. It’s the primary way for the compiler to parse individual expressions, and they are necessary to understand the semantics of the program in the same way indentation is necessary for Python.

Moreover, C# is a strongly typed language, and so much of the syntax of the language is devoted to type specifications for things like variable declarations, variable assignments, function parameters, function return values, etc. The sample above is littered with int and decimal and string and so forth. Quickly you’ll also start to see that types are not just primitives like these but also take the form of complex or user defined classes as well. If you were a Python programmer prior to modern Python (circa 3.6 and above), you would have been more out of place than Python programmers today. Nowadays, type hinting is the latest craze in the Python world, and allows programmers to add similar type specifications in Python to aid in development. Importantly, these type hints are NOT enforced by the Python interpreter but are used in static analyzers like MyPy to provide better program verification during development.

Lastly, C# bakes many attributes of object-oriented programming explicitly into its syntax. For instance, contrary to Python, in C# every class, method, and variable must be declared as public or private (note: you can actually not specify, and the entity will default to private). This is because C# enforces the practice of defining the accessibility of class attributes at the language level, whereas Python does not enforce this concept save through convention (we typically use a leading underscore for this). Similarly, getter and setter methods are specified on class properties in C#, and it is common practice to define custom handlers for these to enforce logic needed to model a particular class. While properties do exist in Python as well, I claim that the average Python programmer takes a much lighter-weight, laissez-faire attitude to variable access and often freely accesses member attributes directly when it makes sense. I should note that one probably just accesses variables directly in C# much of the time as well (for instance, in Unity scripts), the point here is that C# exposes much of the OOP concepts at the syntactic level whereas Python aims to be much less verbose.

Here’s what a “lightweight” Python version of the above C# snippet might look like:

class Pineapple(Fruit):
    def __init__(self, quantity, description, price):
        self.quantity = quantity
        self.description = description
        self.price = price
        self._expired = False
    
    def eat(self, amount):
        if amount <= quantity and !_expired:
            quantity -= amount
            return amount
        return 0

Here’s what a more verbose, type-hinted Python version that uses properties might look like:

class Pineapple(Fruit):
    def __init__(self, quantity: int, description: string, price: float):
        self.quantity: int = quantity
        self.description: string = description
        self.price: float = float
        self._expired = false

    # example of Python property
    @property
    def expired(self) -> bool:
        return self._expired

    @expired.setter
    def expired(self, is_expired: bool) -> None:
        self._expired = is_expired

    def eat(self, amount: int) -> int:
        if amount <= quantity and !expired: # notice no "_"
            quantity -= amount
            return amount
        return 0

Next time, I want to dive into the concept of generics, something that is common in C# but not likely something your average Python programmer has encountered before.

Print Friendly, PDF & Email

Leave a Reply

Your email address will not be published. Required fields are marked *