Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Rust中fn参数的协方差使用什么?_C#_Rust_Covariance - Fatal编程技术网

C# Rust中fn参数的协方差使用什么?

C# Rust中fn参数的协方差使用什么?,c#,rust,covariance,C#,Rust,Covariance,今天我了解到rust不支持fn参数的协方差,只支持其返回类型为协方差。() 为什么我在《铁锈》中了解到了这个事实?因为我试图实现一个非常简单的游戏,在这个游戏中,我将逻辑、事件处理和绘图分为三个不同的函数,但所有函数都在同一个玩家向量上运行 如果不可能,那么与c版本相比,锈蚀的等效值是多少? 在C#中,这相当简单 您可以定义类X必须实现的接口Y,并定义相应的委托,该委托需要该接口Y的IEnumerable作为参数。现在您可以在只需要接口Y的不同方法之间共享X列表 使用系统; 使用System.C

今天我了解到rust不支持fn参数的协方差,只支持其返回类型为协方差。()

为什么我在《铁锈》中了解到了这个事实?因为我试图实现一个非常简单的游戏,在这个游戏中,我将逻辑、事件处理和绘图分为三个不同的函数,但所有函数都在同一个玩家向量上运行

如果不可能,那么与c版本相比,锈蚀的等效值是多少?

在C#中,这相当简单 您可以定义类X必须实现的接口Y,并定义相应的委托,该委托需要该接口Y的IEnumerable作为参数。现在您可以在只需要接口Y的不同方法之间共享X列表

使用系统;
使用System.Collections.Generic;
可操作的公共接口{
无效Do();
}
公共接口可绘制{
无效抽取();
}
公共类玩家:可绘制,可操作{
公营部门{
控制台。写入线(“操作”);
}
公众抽签(){
控制台。写入线(“绘制”);
}
}
公共课程
{
公共委托无效DrawHandler(IEnumerable obj);
公共委托无效逻辑处理程序(IEnumerable obj);
公共静态void游戏循环(DrawHandler draw,LogicHandler动作){
列表=新列表(){
新玩家()
};
用于(整数轮数=0;轮数<500;轮数++){
抽签(名单);
行动(清单);
}
}
公共静态void Main()
{
游戏圈(
列表=>{
foreach(列表中的变量项){
item.Draw();
}
},
列表=>{
foreach(列表中的变量项){
item.Do();
}
}
);
}
}
虽然我很天真,但我试着在《铁锈》中做一些与之相当的事情

trait可绘制{
fn绘制(和自绘制){
println!(“绘制对象”);
}
}
可采取行动的特征{
fn do_操作(&self,操作:&String){
println!(“Do{}”,action);
}
}
#[导出(调试)]
结构位置{
x:u32,
y:u32,
}
植入位置{
fn新(x:u32,y:u32)->位置{
位置{x,y}
}
}
#[导出(调试)]
结构播放器{
位置:位置,
名称:String,
}
impl播放器{
fn新(名称:字符串)->播放器{
玩家{
名称
位置:位置::新建(0,0),
}
}
}
可供玩家使用的嵌入式绘图{
fn绘制(和自绘制){
println!(“{:?}”,self);
}
}
可为玩家执行的impl{
fn do_操作(&self,操作:&String){
println!(“Do{}{}!”,action,self.name);
}
}
类型DrawHandler=fn(可提取项:&Vec)->结果;
类型LogicHandler=fn(操作:&Vec)->结果;
类型EventHandler=fn(事件:&mutsdl2::EventPump)->结果;
fn博弈循环(
窗口:&mut windowContext,
draw_handler:DrawHandler,
事件处理程序:事件处理程序,
逻辑处理器:逻辑处理器,
)->结果{
让mut对象:Vec=Vec::new();
objects.push(&Player::new(“b.to_string());
而事件处理程序(&mut window.events){
逻辑处理程序(&对象);//不工作
window.canvas.clear();
绘制处理程序(&对象);//不起作用
window.canvas.present();
::std::thread::sleep(持续时间::new(0,1_000_000_000u32/60));
}
好(())
}
如果不可能,那么与c版本相比,锈蚀的等效值是多少?


我承认这在铁锈中是不可能的。我想知道在rust中使用的是什么

在rust中,很少有隐式操作,包括您发现的铸造

在这种情况下,将
Vec
转换为
Vec
是不可能的(假设
T!=dyn Trait
),因为Trait对象是如何存储的;它们是两个指针宽度,而普通引用是一个指针宽度。这意味着
Vec
的长度(以字节为单位)需要加倍

我承认这在铁锈中是不可能的。我想知道防锈剂中使用的是什么

如果您只使用一种对象,则可以限制其类型:

type DrawHandler = fn(drawables: &Vec<Player>) -> Result<(), String>;
type LogicHandler = fn(actions: &Vec<Player>) -> Result<(), String>;
  • 使用ECS,它可以根据任意对象的属性管理任意对象。锈迹中存在的一些ECS有:

    • 还有一些
    通常,它们的用法如下所示:

  • fn game_loop(
        draw_handler: DrawHandler,
        logic_handler: LogicHandler,
    ) -> Result<(), String> {
        let mut objects: Vec<Player> = Vec::new();
    
        objects.push(Player::new("b".to_string()));
    
        for i in 0..1 {
            let actionable = objects.iter().map(|v| v as &dyn Actionable).collect();
            logic_handler(&actionable)?; // Does work!
    
            let drawables = objects.iter().map(|v| v as &dyn Drawable).collect();
            draw_handler(&drawables)?; // Does work!
        }
    
        Ok(())
    }
    
struct DrawingComponent{
缓冲区:缓冲区
}
结构方向{
方向:矢量
}
结构位置{
位置:点
}
让mut world=world::new();
insert((DrawingComponent::new(),DirectionAI::new(),Position::new());
用于世界上的(位置、方向)。iter_超过(::query()){
位置位置+=方向方向;
}
用于世界上的(pos,可绘制)。iter_over(::query()){
可拉拔缓冲器设置位置(*位置);
牵引(可牵引);
}
在这个系统中,您一般在组件上工作,而不是在类型上工作。这样,ECS可以非常快速、高效地存储和访问项目


锈菌的协变性确实存在。这不是OOP协方差,而是整个生命周期的协方差,因为这对日常用户来说是一件利基的事情


请注意,该部分中的表格涵盖了
'a
T
,以及在某些情况下,
U
的差异。在
T
U
的情况下,其中的方差存在于它们可能具有的任何寿命参数中,而不是类型本身。也就是说,它描述了如何将
'b
结构中的变体(或不变)转换为
dyn Trait+'b

&Player
视为
&dyn Drawable
看起来像是在超级类型中使用子类型,但实际上它是一种类型转换(两者在内存中看起来完全不同@更详细地解释了这一点)