繁体   English   中英

将JavaScript转换为C# - 构造函数和数组的难度

[英]Converting JavaScript to C# - difficulty with constructors and arrays

我正在努力学习C#并且我是全新的,如果我的问题非常基础,那就很抱歉。 当我学习新语言时,我喜欢使用我现有的一些代码并尝试翻译它(它可能不适用于所有人,但我发现它对个人非常有帮助)。 我之前在JavaScript中创建了一个小型机场程序,并希望在C#中构建相同的程序。

一段JavaScript代码:

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

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

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

但是,我正在努力在C#中编写类似的代码,尤其是构造一个具有空数组平面的Airport对象(我还将有一个单独的Plane类)。 我做了以下尝试:

using System;
namespace Airport
{
    public class Airport
    {

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

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

但是我不相信这是构建机场班级的正确方法。 此外,我收到错误'类中的无效标记字符串'。 我们欢迎所有的建议?

谢谢!

您的机场在概念上是飞机的容器(您现在使用的是字符串;我们可以稍后升级到飞机)所以您需要在班级级别声明您的飞机列表的存储

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       
        }
    }
}

JS和C#之间的一个巨大差异是变量的范围。 在C#中,声明的变量通常仅在{ curly brackets }内可用,并且在任何子花括号中定义。 变量在声明之前不可用:

//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

它更像是JS中的“let”

稍后,将Plane建模为自己的对象会更有意义:

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;
  }


}

然后你将堆栈修改为堆栈。 你也会修改你的方法返回类型..

就个人而言,我不会使用Stack for Planes,因为它意味着唯一可能起飞的飞机是最近降落的飞机。 飞机可以以与他们在机场降落的顺序无关的随机顺序起飞,因此请考虑使用List<Plane> 这样你可以通过注册找到一架飞机并将其从机场中移除:

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;
    }
  }
}

如果你改变了东西,那么它就是List<Plane即一个包含Plane对象的List,那么你就不能将一个字符串推入它,所以你的Land需要看起来像下面的一个:

        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);
        }

有很多方法可以简化后者,但我已经做了很长时间才能说清楚

你试图返回什么都没有的void ,你也试图从这个函数返回一个string ,你需要在其中一个之间做出决定,在同一个函数中,例如你没有返回任何东西,所以我会保留void关键字并删除string

尝试

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);
        }

    }
}

正如安德烈亚斯所说,这是C#的基础知识是强类型的。 C#具有类继承,而JavaScript基于(无类)原型继承,这是不同的概念。 但是从ES2015开始,JavaScript也支持类继承。

我的建议是开始深入研究基本的C#和类继承,不要太担心翻译代码。 如果你真的想要它,只需重建机场计划,并比较两者之间的差异,如果你真的希望如此。

我不是C#dev,但我尝试了这个并获得了以下结果:

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] + ", ");
            }
        }
    }
}

我知道即时通讯使用字符串数组而你想要'平面'对象,但我没有'平面'对象。 您基本上必须更改阵列的类型和测试输出

在网上尝试一下!

除了Caius Jard的答案之外我还摆弄了这样的东西:

我做了一个名为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();
        }
    }
}

如您所见,它可能包含一个平面列表而不是一个字符串集合。 使用平面作为对象而不是字符串将是处理逻辑的更强大的方法,因为您可以设置属性并为平面创建方法,而不是使用大量的变量(就像在纯JavaScript中一样)做同样的事情为了实现飞机的处理。

另外(在我看来,我认为还有很多其他的),它在阅读OOP(面向对象编程)代码时更容易阅读。 在JavaScript中,你也可以使对象实现类似的东西,但这将是一个不同的主题。

Plane类看起来像这样:

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.");
        }
    }
}

也许如果你想将一个对象作为属性添加到另一个对象,这就是你可以按照我定制的GeolocationSystem类来做到的:

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);
        }
    }
}

然后,如果您想调用方法和/或创建类的对象实例,您可以执行以下操作:

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);
        }
    }
}

这只是一些示例代码,展示了如何实现您想要实现的任何目标。 如果您需要任何帮助来确定我的示例代码如何工作或需要有关OOP C#的任何其他建议,您可以发表评论。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM