Angband Forums

Angband Forums (http://angband.oook.cz/forum/index.php)
-   Development (http://angband.oook.cz/forum/forumdisplay.php?f=10)
-   -   C#, Angband and Unity (http://angband.oook.cz/forum/showthread.php?t=7294)

Derakon April 14, 2015 15:43

Quote:

Originally Posted by the Invisible Stalker (Post 100507)
Just be glad it doesn't have signed bits.

I guess then your options are +0 and -0.

AnonymousHero April 15, 2015 01:40

Quote:

Originally Posted by the Invisible Stalker (Post 100507)
Just be glad it doesn't have signed bits.

Well, let's see what they have to say about the inevitable trail of bodies... BITS! I MEAN BITS!.

Dean Anderson April 17, 2015 10:38

I've been making slow but steady progress, and while I've not found anything near a showstopper, here are my top seven (it was going to be a top five but I thought of a couple more) irritations when porting Cthangband from C to C#...
  1. C# is very finicky about casting. Much more so than C, where you can interchange pretty freely between numbers of different types (byte, int16, int32, signed and unsigned). Where C will generally simply let you copy a value from one type to another and not care if it doesn't fit - you'll just get roll-overs and possibly unexpected results - C# insists on explicit casting. All the time. Not a problem when you're writing new C# code, but a pain when porting old C code.
  2. C doesn't do strings at all well. You have to fiddle around with arrays of characters, pointers, and null terminators. None of that is necessary in C# but again it's very irritating to convert because in C# you don't (explicitly) use pointers (you do actually use them all the time when using reference types, but they're implicit rather than explicit).
  3. C lets you do if statements on numbers, for example if i is an int, you can write "if(i)" and the compiler will understand that you mean "if(i != 0)". C# will throw a compiler error because if statements need to look at a bool rather than an int. So you have to manually add the explicit comparison to zero on each one.
  4. Speaking of bools, C# is very strict that a bool is not a number and a number is not a bool and never the twain shall meet. C doesn't really care, and the C in Angband uses its own preprocessor definitions of TRUE and FALSE which have nothing to do with C#'s true and false.
  5. Did I mention preprocessor definitions? In C# these are all boolean. Either a term is #defined or it isn't. You can't #define a term as a value and then use the term as a macro for that value elsewhere in your code. Well, you can for value types, but the syntax is different. They're declared as variables but with the "const" decorator. You can't do things like "#define SUM(A,B) (A) + (B)" though.
  6. In C#, everything is in an encapsulated unit of code. The majority of the time these are classes but you also have enumerations, interfaces and structs (although the latter are mostly there for API compatibility with C and there's no reason to ever use them in native C# code). There's no such thing as a global scope for variables or functions, they have to be declared inside a class or struct. The closest you can get to a global variable is to give a class a static property or even make the whole class static. In C, of course, every function and variable is global. So that variable in the C code that is declared as being external and then used 269 times in the file as if it were local? Every single one of those 269 times need to be prefixed with the name of the class in which you've declared it in C#.
  7. In C you declare that a variable is an array by decorating the variable's name. In C# you do it by decorating its type. For example in C you have "int x[] = {0, 1, 2, 3, 4}". The equivalent code in C# is "int[] x = new int[] {0, 1, 2, 3, 4}". Similarly where C has "int x[5]", C# has "int[] x = new int[5]". These are functionally identical for the most part, but it's a pain having to change each declaration.

And of course, the thing that's really making me twitch is the fact that I know I'm going to be rewriting most of this code in the next stage of the process where I refactor everything. All the initialisation code I've ported? It's going to be in constructors, not static initialisation functions. All the global stuff? It's going to be in a nice object model, not just scattered around a whole bunch of static classes. All the loading and saving code that reads and writes files byte by byte and has to handle every global variable independently? It's going to just serialize and deserialize the object tree in a half dozen lines of code.

But I have to port it as-is first and get everything working before I start doing the refactoring. Trying to port and refactor the code in a single pass will just end up in a mess.

the Invisible Stalker April 17, 2015 15:15

It's interesting for me, as someone with no C# experience, to see the list of differences. On the whole I prefer C's design choices, but not in all cases. I'd guess that in the course of dealing with point 1 on your list you'll find some bugs that have gone unnoticed for years because the Intel architecture is so ubiquitous. It's easy to get used to assuming things about integer sizes which aren't mandated by the standard.

Dean Anderson April 17, 2015 16:10

They're not the only differences between the languages, of course; but they're the things that are fiddly to convert.

In terms of preference, it's generally a matter of horses for courses. C# is similar to Java in that its designed around you having a virtual machine in which security and safety are paramount. That's why it has so much more emphasis on casting things properly. You can't just throw around pointers and treat any bit of memory as any type of data. Many of the design choices are based around that, including the use of garbage collection based memory management.

Personally, I prefer C# to C but that's mostly because I've been using C# every day at work for over a decade, and other than Angband I've not used C in that time. So these days I'm far more familiar with the way C# works than the way C works. Plain C certainly has its advantages when it comes to places where you need to be close to the hardware. And it gives you fine detailed control over memory and the like. But those advantages can all to often become disadvantages at times when you don't need that closeness or control - at which point you tend to still need the detail and that can get really fiddly. And for OO code I definitely prefer C# or Java - both languages designed to be OO from the ground up - than C++, which has always struck me as a bit of a kludge.

AnonymousHero April 17, 2015 17:18

Quote:

Originally Posted by Dean Anderson (Post 100632)
{#5:} Did I mention preprocessor definitions? In C# these are all boolean. Either a term is #defined or it isn't. You can't #define a term as a value and then use the term as a macro for that value elsewhere in your code. Well, you can for value types, but the syntax is different. They're declared as variables but with the "const" decorator. You can't do things like "#define SUM(A,B) (A) + (B)" though.

This is one of those things where I've just gone through all the C code and changed the macros to functions (well, almost all). It's not like anybody's going to notice any performance difference these days.

Quote:

Originally Posted by Dean Anderson (Post 100632)
{#6}: In C#, everything is in an encapsulated unit of code. The majority of the time these are classes but you also have enumerations, interfaces and structs (although the latter are mostly there for API compatibility with C and there's no reason to ever use them in native C# code). There's no such thing as a global scope for variables or functions{..} Every single one of those 269 times need to be prefixed with the name of the class in which you've declared it in C#.

I actually wondered at one point whether one should just copy everything into a single class (aside from pure struct declarations, etc., obviously), get that working and then just start using IDE refactorings to split things out.

It'd be a monster file (~140SLOC for T2.x on current master), but it really would be "just" a matter of going through from one end to the other. (Of course now you have to deal with clashing compilation-unit local statics, but I bet that's a smaller problem.)

Quote:

Originally Posted by Dean Anderson (Post 100632)
But I have to port it as-is first and get everything working before I start doing the refactoring. Trying to port and refactor the code in a single pass will just end up in a mess.

Agreed. I might consider a similar port in future, but I think I'm going to go a slightly different way and to get rid of some of the absolutely ridiculous amount of code (near-)duplication (using C++ and possibly a little bit of templates) before even attempting it.

AnonymousHero April 17, 2015 19:58

Re: Duplicate code: Case in point: just removed 715 (EDIT: 754) lines of redundant code with completely trivial template use :)

ekolis April 17, 2015 21:03

C# 5.0 will support static imports, much like Java, so instead of saying

import System;
...
Console.WriteLine("hello world");
Console.WriteLine("isn't it annoying to have to type Console all the time?");

you can say

import System.Console;
...
WriteLine("hello world");
WriteLine("yay I don't have to type Console anymore :)");

Dean Anderson April 17, 2015 22:14

Quote:

Originally Posted by AnonymousHero (Post 100654)
I actually wondered at one point whether one should just copy everything into a single class (aside from pure struct declarations, etc., obviously), get that working and then just start using IDE refactorings to split things out.

It'd be a monster file (~140SLOC for T2.x on current master), but it really would be "just" a matter of going through from one end to the other. (Of course now you have to deal with clashing compilation-unit local statics, but I bet that's a smaller problem.)

I should have thought of that. In C# it wouldn't even need to all be in a single monster file because you can use the "partial" keyword when defining a class to indicate that it's split between files.

Dean Anderson April 20, 2015 22:23

Interesting things I learned today #1: The Angband code still contains "goto" statements!

Interesting things I learned today #2: "goto" statements will compile under C# without error.

Those things are so coming out when I do the refactoring!


All times are GMT +1. The time now is 23:05.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2019, vBulletin Solutions Inc.