1

I am trying to learn C# and am completely new to it so sorry if my questions are very basic. When I learn new languages, I like to use some of my existing code and try to translate it (it might not work for everyone but I find it quite helpful personally). I have previously made a small Airport program in JavaScript and wish to build the same program in C#.

A snippet of the JavaScript:

var Airport = function(){this.planes = []};

Airport.prototype.land = function(plane) {
  this.planes.push(plane);
};

Airport.prototype.takeoff = function(plane) {
  this.planes.pop();
};

However, I am struggling to write similar code in C#, especially constructing an Airport object with an empty array of planes (I will also have a separate Plane class). I have made the following attempt:

using System;
namespace Airport
{
    public class Airport
    {

        public Airport(string planes)
        {
            string[] planes = { };
        }

        public void string Land(object plane)
        {
            planes.Add(plane);
        }
    }
}

However I am not confident that this is the correct way to construct the Airport class. Also, I get the error 'Invalid token string in class'. Any suggestions would be much appreciated?

Thank you!

4
  • 1
    This (data types, classes) is topic of every C# beginners tutorial. Commented Aug 1, 2019 at 11:13
  • void and string should not be combined for a method. Either you return nothing and it is just a method (a.k.a. a function like a JavaScript function) or you return something like a number (which would return as an int (integer) in C#) or a piece of text (which would return as a string in C#). In the example you provided you are not returning a string, so you might want to consider removing string from public void string Land(object plane). Commented Aug 1, 2019 at 11:25
  • Variables scope is wrong. string planes[] should be declared outside the class constructor. Commented Aug 1, 2019 at 11:34
  • I would also recommend you to stick with just using the void keyword alone for creating (void) methods until you learn to understand how to return certain types (like string and integer) to keep things simple. Commented Aug 1, 2019 at 11:57

6 Answers 6

3

Your airport is conceptually a container for planes (you're using strings now; we can upgrade to planes later) so you need to declare the storage of your list of planes at the class level

namespace Airport
{
    public class Airport
    {
        //this will hold the planes. I choose Stack<> rather than string[] because arrays are not push/pop'able in c# and youre using your javasscript array like a stack (LIFO)
        private Stack<string> _planes = new Stack<string>();

        public Airport() //you don't need to pass anything to your airport when you construct it
        {
        }

        //In c# method declarations look like:
        //<AccessModifier> <ReturnType> <MethodName>(<ArgumentList>)
        //Methods cannot be marked as "void string" as a return type - you must choose either void (if it returns nothing) or string(if it returns a string). 
        //If it returns something else one day, like a Plane object, it should be marked as returning Plane. 
        //Your JS Land method returns nothing so I declare void
        public void Land(string plane){
            _planes.Push(plane);
        }

        public string Takeoff() //this returns a plane, so we declare the return type as string
        {
            return _planes.Pop(); //need to handle errors if the planes list is empty btw       
        }
    }
}

One massive difference between JS and C# is scoping of variables. In C# a variable declared is typically only available inside the { curly brackets } it is defined in plus any child curly brackets. Variables are not available before they're declared:

//s not available here

if(a==b){
  //s not available here

  string s = "s";
  //s available here

  if(c==d){
    //s available here

  }
  //s available here

} 
//s not available here

It's more like "let" in JS

Later it will make more sense to model a Plane as its own object:

class Plane{
  public string Registration { get; set; } //reg can be changed during plane life
  public int NumberOfEngines { get; private set; } //read only to the rest of the world, as the engine count doesn't change, but needs to be writable internally to this class so the property can be set

  public Plane(int numberOfEngines){ //make numberOfEngines a constructor parameter to force it to be filled in when the plane is constructed. Registration is unknown at time of manufacture
    NumberOfEngines = numberOfEngines;
  }


}

Then you'd modify your Stack to be a Stack. And you'd modify your method return types too..

Personally, I wouldn't use Stack for Planes, because it implies the only plane that may take off is the one that most recently landed. Planes can take off in a random order unrelated to the order they landed at the airport, so consider a List<Plane> instead. That way you could find a plane by its registration and remove it from the airport:

public Plane Takeoff(string reg){
  for(int i = 0; i < _planes.Count; i++) {
    if(_planes[i].Registration == reg){
       Plane p = _planes[i];
       _planes.RemoveAt(i);
       return p;
    }
  }
}

If you've changed things so that it's List<Plane i.e. a List that holds Plane objects then you cannot push a string into it so your Land will need to look like one of the below:

        public void Land(Plane plane){
            _planes.Push(plane);
        }

        public void Land(string reg, int numberOfEngines){
            Plane p = new Plane(numberOfEngines);
            p.Registration = reg;
            _planes.Push(p);
        }

There are plenty of ways to shortcut the latter but I've done it out long hand to make it clear

Sign up to request clarification or add additional context in comments.

2 Comments

Is it true that "Methods are either void or string as a return type"? Should you not explicitly tell your compiler whether it is dealing with a string as return type and if not, describe your method as "void"? For as far as I know a method could return anything really. From integers, to objects, lists, dictionaries and whatnot.
@CaiusJard Thank you also for your suggestions to model the Plane as its own object. I have created a Plane class and also changed Stack to List as suggested but am struggling to pass the objects as arguments - planes.Add(plane) says that I cannot convert an object to a string. Can I not just add the plane object to the List without it being a string?
0

you are trying to return void which is equal to nothing, and you're also trying to return a string from this function, you need to decide between one of those, in this same function for example you are not returning nothing, so i would keep the void keyword and delete the string

Comments

0

As Andreas said this is the basics of C# of which is strongly typed. C# has class inheritance while JavaScript is based on (classless) prototypical inheritance, which are different concepts. However as from ES2015, JavaScript also supports class inheritance.

My suggestion is just start dive in looking at basic C#, and class inheritance, do not worry much about translating the code. Just rebuild the airport program if you really want it and compare the differences between the two if you really wish so.

Comments

0

try

using System;
using System.Collections.Generic;

namespace Airport
{
    public class Airport
    {
        private readonly List<string>  planes;
        public Airport()
        {
            planes = new List<string>();
        }

        public void Land(string plane)
        {
            planes.Add(plane);
        }

        public void TakeOff(string plane)
        {
            planes.Remove(plane);
        }

    }
}

1 Comment

Consider adding some extra info in your answer, like for example variable scope (the main problem OP had)
0

I am not a C# dev but i tried this out and got following result:

using System;

namespace Flughafen
{
    public class Airport
    {
        private string[] planes;

        public Airport(string[] planes) 
        {
            this.planes = planes;
        }

        public void land(string plane)
        {
            string[] helper = new string[planes.Length+1];

            for (int i = 0; i < planes.Length; i++)
            {
                helper[i] = planes[i];
            }
            helper[planes.Length] = plane;
            this.planes = helper;
        }

        public void takeOff(string plane)
        {
            string[] helper = new string[planes.Length];
            int k = 0;
                for (int i = 0; i < planes.Length; i++)
                {
                    if (planes[i] == plane)
                        i++;
                    helper[k++] = planes[i];
                }
            this.planes = helper;
        }

        public string[] getAirport()
        {
                return this.planes;
        }

    }
}
namespace Rextester 
{
    public class Program 
    {
        public static void Main(string[] args) 
        {
            Flughafen.Airport a = new Flughafen.Airport(new string[3] {"1", "2", "3"});
            a.land("4");
            a.takeOff("1");

            string[] b = a.getAirport();
            for (int i = 0; i < b.Length-1; i++)
            {
                    Console.Write(b[i] + ", ");
            }
        }
    }
}

I know that im using String Arrays and you wanted 'plane' object but i dont have a 'plane' object. You basically have to change the types and the test output of the array

Try it out online!

2 Comments

Could you elaborate, why did you make the Airport.planes property private (as I am someone who is still learning C# as well)?
Dont permit other classes to use the variables value access the variables with method. Why C# says to access variables through methods because suppose if the value of variable is not as expected then the application can throw RunTime Exception. To avoid such senerio we can use getter and setter method. How they are useful : Getter Method : While getting the value of a varible we can check in the method that it is initialised or not. Setter method : While setting the value we can check and so something on the value before setting into variables.
-1

In addition to Caius Jard's answer I fiddled something like this:

I made a class called Airport:

namespace Airport
{
    public class Airport
    {
        // Properties of Airport object:
        public int Id { get; set; }
        private List<Plane> Planes { get; set; }

        // Constructor method for Airport object:
        public Airport(int id, List<Plane> planes)
        {
            Id = id;
            Planes = planes;
        }

        // A method to remove planes from the airport's collection (just an example of how OOP could be used to make "readable" code):
        public void RemoveDepartedPlane(int id)
        {
            if(Planes.Exists(x => x.Id == id))
            {
                Planes.Remove(Planes.Find(x => x.Id == id));
            }
            Console.WriteLine("A plane by id: {0} has been removed from available planes on this airport", id);
        }

        // A method to add arrived planes to the airport's collection:
        public void AddArrivedPlane(int id)
        {
            // Custom made class called Coordinate:
            Coordinate coordinate = new Coordinate(0, "Airportlocation");
            // Custom made class called GeolocationSystem (which I just came up with):
            GeolocationSystem geolocationSystem = new GeolocationSystem(0, "", "", DateTime.Now, coordinate);
            Planes.Add(new Plane(id, "", "", "", geolocationSystem));
        }

        // Gets the amount of used up spaces of planes on current airport
        public int GetUsedSpaces()
        {
            return Planes.Count();
        }
    }
}

As you can see, it might be able to contain a list of planes rather than a collection of strings. Using a plane as object rather than a string would be a more powerful way to handle your logic, as you can set properties and make methods for the plane instead of making tons and tons of variables (like you would in plain JavaScript) doing the same for the purpose of achieving the handling of planes.

Also (in my opinion and I think many others too), it reads easier and makes more sense when going through OOP (object oriented programming) code. In JavaScript you could also make objects to achieve similar things, but that would be a different subject.

The Plane class could look something like this:

namespace Airport
{
    public class Plane
    {
        public int Id { get; set; }
        public string Type { get; set; }
        public string Name { get; set; }
        public string Color { get; set; }
        public GeolocationSystem GeolocationSystem { get; set; }

        public Plane(int id, string name, string type, string color, GeolocationSystem geolocationSystem)
        {
            Id = id;
            Name = name;
            Type = type;
            Color = color;
            GeolocationSystem = geolocationSystem;
        }

        // All sorts of methods belonging to a plane:
        public void TakeOff()
        {
            Console.WriteLine("Taking off!");
        }

        public void AutoPilot()
        {
            Console.WriteLine("Autopiloting...");
        }

        public void Land()
        {
            Console.WriteLine("Now landing...");
        }

        public void TurnLeft()
        {
            Console.WriteLine("Turning left.");
        }

        public void TurnRight()
        {
            Console.WriteLine("Turning right.");
        }

        public void Ascend()
        {
            Console.WriteLine("Ascending.");
        }

        public void Descend()
        {
            Console.WriteLine("Descending.");
        }
    }
}

And maybe if you want to add an object as property to another object, this is how you could do it per my custom made GeolocationSystem class:

namespace Airport
{
    public class GeolocationSystem
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Type { get; set; }
        public DateTime TimeStamp { get; set; }
        public Coordinate Coordinate { get; set; }

        public GeolocationSystem(int id, string name, string type, DateTime timeStamp, Coordinate coordinate)
        {
            Id = id;
            Name = name;
            Type = type;
            TimeStamp = timeStamp;
            Coordinate = coordinate;
        }

        public void GetLocation()
        {
            Console.WriteLine("Location of current system is at coordinate: {0}, at time: {1}.", Coordinate.Value, TimeStamp);
        }

        public void GetSystemInfo()
        {
            Console.WriteLine("System name: {0} {1} and is type: {2}.", Id, Name, Type);
        }
    }
}

Then if you would like to call methods and/or create object instances of the classes, you could do something like this:

namespace Airport
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create any object required for making an instance object of the airport:
            List<Plane> planes = new List<Plane>();
            // Then create an instance of the airport:
            Airport airport = new Airport(0, planes);
            // Now that the airport exists (as an object), you could now access its properties and/or methods and set and/or use these:
            // Set Planes in airport's plane collection:
            for (var i = 0; i < 10; i++)
            {
                airport.AddArrivedPlane(i);
            }
            // "Read" the collection:
            Console.WriteLine(airport.GetUsedSpaces());
            // Or you could play around with the Plane class (or an object of that type): 
            Plane plane = new Plane(0, "", "", "" , new GeolocationSystem(0, "", "", DateTime.Now, new Coordinate(0, "")));
            plane.TakeOff();
            Console.ReadKey(true);
        }
    }
}

This is just some example code to show how you could achieve whatever you are trying to achieve. If you need any help figuring out how my example code works or need any other advice regarding OOP C#, you could leave a comment.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.