所以我习惯使用javascript,只能做
dog={};
dog.name="Rex";
dog.examine=function(){console.log("This is a dog. Its name is "+this.name+".");}
cat={};
cat.name="Phil Collins";
cat.examine=function(){console.log("This is a cat. Its name is "+this.name+".");}
dog.examine();
cat.examine();
当然会返回: This is a dog. Its name is Rex.
和 This is a cat. Its name is Phil Collins.
我开始学习xna,我对整个lambda
/ delegate
/ action
系统感到非常困惑。我不确定使用什么语法,编译器在我尝试创建没有输入或输出变量的函数时会生气,而且我无法保持 this
。有人可以帮我看看我如何将上述代码移植到c#?
答案 0 :(得分:4)
我将其设为社区Wiki,因为这个问题实在太宽泛,C#和JavaScript是非常不同的东西,答案也不完整。我只是简单地描绘一个方向,但是要走的路是学习C#,差异很明显。这就是为什么我会尝试首先将类似写入您发布的JavaScript程序,然后逐步将其更改为更多C#样式。
我还要说,如果你非常想在C#(或JavaScript编程风格)中使用动态类型,那么(可能)......你选择了错误的语言。
某种接近你所写的东西可以用C#写成这样的(让我用这个例子来强调差异,你真的必须买一本好的C#书并从那里开始):
dynamic dog = new ExpandoObject();
dog.Name = "Pluto";
dog.Hello = new Action(() => Console.WriteLine("This is a dog named {0}", dog.Name));
dog.Hello();
dynamic
我们绕过静态类型,我们甚至可以在以后更改内容(但这是另一个故事)。 ExpandoObject
是一个特殊对象,可以扩展添加属性,它不是普通 C#行为,其中几乎所有关于类型的内容都在编译时检查(不要想想演员,现在)。this
在C#中有不同的含义方法this
是声明方法的对象的实例(确定它在类中声明,但你知道我的意思)。让我们看一下:dog.Name
,我们在我们的匿名方法中捕获 dog
变量(就像在JavaScript中一样)。这只是一个起点,因为设计和哲学是完全不同的,C#中的相同内容应该使用Animal
基类和Dog
+ Cat
派生类来完成,但是你会自己学习。让我在这方面做一个简单的步骤:
var typedDog = new {
Name = "Pluto",
Hello = new Action(() => Console.WriteLine("This is a dog named {0}", Name))
};
typedDog.Hello();
也许你没有看到如此大的差异,但这个代码是强类型的!这是什么意思?我们声明了一个带有两个属性的匿名类,其中一个是委托,我们仍然不能使用this
而在C#中(与Java不同)我们不能在匿名类型中声明方法,但现在编译器知道了(那么它是什么东西都是编译时间。例如:
dog.Name = 2; // Valid, now Name is an integer
dog.Hello = 2; // Valid, also Hello is an integer
dog.Hello(); // This will fail at run-time because Hello now isn't a delegate
不好吗,对吧?使用我们的新类型对象,这是不可能的:
typedDog.Name = 2; // Compile-time error, Name is a string
typedDog.Hello = 2; // Compile-time error, Hello must be an Action delegate
当然我们可以指定一个新的匿名委托来替换旧的(但类型必须匹配):
typedDog.Hello = new Action(() => Console.WriteLine("This is a typed dog named {0}", typedDog.Name));
这已经在其他答案中得到了广泛的描述,所以我不再重复,只是为了草拟一些事情:
class Animal {
public string Name { get; set; }
public abstract void Hello();
}
class Dog : Animal {
public override void Hello() {
Console.WriteLine("This is a dog named {0}", this.Name);
}
}
请注意,现在您终于拥有了this
指针,它可以满足您的期望。它的使用方式如下:
var dog = new Dog { Name = "Pluto" };
dog.Hello();
请注意,在JavaScript中,您甚至可以写下这个:
var anInteger = 2;
anInteger.PrintSomething();
在C#中不允许这样做,因为在编译时(除非你使用dynamic
个变量),它需要知道PrintSomething()
是否是一种方法以及如何调用它。同样的事情也可以这样做(使用接口):
class IPolite {
void Hello();
}
class Dog : IPolite {
public string Name { get; set; }
public void Hello() {
Console.WriteLine("This is a dog named {0}", this.Name);
}
}
现在你甚至可以拥有一个完全不同的对象:
class Car : IPolite {
public string Name { get; set; }
public void Hello() {
Console.WriteLine("This is a car, name is {0}", this.Name);
}
}
可以像这样使用:
IPolite thing = new Dog { Name = "Pluto" };
thing.Hello();
thing = new Car { Name = "Ferrari F50" };
thing.Hello();
请注意我们正在重复使用相同的thing
变量。许多其他事情要看和做...
答案 1 :(得分:2)
通常,C#和其他强类型语言与JS等脚本/运行时语言完全不同。 C#是一种编译语言,编译器确保了这种“强类型”特性。对于许多类型安全(http://en.wikipedia.org/wiki/Type_safety)语言都是如此。
一般来说,C#中的类结构如下所示:
public abstract class Animal {
//Fields or instance variables are typically hidden from the outside world (consuming code). This is controlled by the 'access-modifier' in this case, private.
private string _name;
//Constructor is called when you use the 'new' keyword to instantiate an instance of a type that derives from Animal (Animal cannot be instantiated directly because it is abstract).
protected Animal() {
//Avoids null references unless someone overrides the property setter, for this example, it's safe enough
_name = string.Empty;
}
//This is syntax for declaring a property
//properties are publicly accessible pieces of data that control access to a basic
// field (variable).
// It allows you to apply logic to the field it wraps.
// In this example, the field cannot be set to a null or empty string (except by the constructor, which bypasses the property.
public virtual string Name {
get {
return _name;
} set {
if(!String.IsNullOrWhiteSpace(value)) {
_name = value;
}
}
} // end property Name
//This is a method that must be overridden by any derived type that is not abstract and may (or may not) be overridden by a derived type that is abstract.
public abstract void Examine();
}
public class Cat : Animal {
public Cat : base() {}
public override void Examine() {
Console.WriteLine(String.Concat("This is a cat. It's name is ", this.Name, "."));
}
}
public Class Dog : Animal {
public Dog() : base() {}
public override void Examine() {
Console.WriteLine(String.Concat("This is a dog. It's name is ", this.Name, "."));
}
}
//In some runnable code elsewhere like a console application:
Animal cat = new Cat() {Name = "Mittens"};
Animal dog = new Dog() {Name = "Fido"};
cat.Examine();
dog.Examine();
答案 2 :(得分:0)
您可以使用继承来完成它:
public class Animal
{
public string Name { get; private set; }
public Animal(string name)
{
this.Name = name;
}
public void Examine()
{
Console.WriteLine("This is a {0}. Its name is {1}.", this.GetType(), Name);
}
}
public void Dog : Animal
{
public Dog(string name) : base(name) { }
}
public void Cat : Animal
{
public Cat(string name) : base(name) { }
}
然后您可以创建这些派生类型的实例:
static class Main(string[] args)
{
Dog rex = new Dog("rex");
Cat phil = new Cat("Phil Collins");
rex.Examine();
phil.Examine();
}
答案 3 :(得分:0)
这是一个简单的例子。我强烈建议你拿一本书或者查看一个教程,因为这些东西很早就会被提及。
public abstract class Animal
{
public string Type { get; private set; }
public string Name { get; set; }
protected Animal(string type)
{
Type = type;
}
public virtual string Examine()
{
return string.Format("This is a {0}. Its name is {1}.", Type, Name);
}
}
public class Dog : Animal
{
public Dog() : base("Dog")
{
}
}
public class Cat : Animal
{
public Cat() : base("Cat")
{
}
}
var dog = new Dog { Name = "Rex" };
var cat = new Cat { Name = "Phil Collins" };
答案 4 :(得分:0)
您可以使用所谓的匿名函数,也可以将您的此函数作为Action类型的属性。例如,你可以写:
Animal.cs:
public abstract class Animal
{
public string Name { get; set; }
public Action Examine { get; set;}
}
Dog.cs:
public class Dog : Animal
{
}
Cat.cs:
public class Cat : Animal
{
}
然后,在某个你可以使用它的地方,你可以说:
Dog dog = new Dog { Name = "Rex" };
dog.Examine = delegate
{
Console.WriteLine("This is a dog. Its name is {0}.", dog.Name);
};
Cat cat = new Cat { Name = "Phil Collins" };
cat.Examine = delegate
{
Console.WriteLine("This is a cat. Its name is {0}.", cat.Name);
};
dog.Examine();
cat.Examine();
请记住,不是使用'this',而是使用对以前实例化的类的引用,该类扩展了Animal(Dog或Cat)。
还有另一个选项......组合ExpandoObject类和动态关键字:
dynamic dog = new ExpandoObject();
dog.Name = "Rex";
Action examineDog = delegate {
Console.WriteLine("This is a dog. Its name is {0}.", dog.Name);
};
dog.Examine = examineDog;
dynamic cat = new ExpandoObject();
cat.Name = "Phil Collins";
Action examineCat = delegate
{
Console.WriteLine("This is a cat. Its name is {0}.", cat.Name);
};
cat.Examine = examineCat;
dog.Examine();
cat.Examine();