【问题标题】:Handle downcast error when downcasting Ref<Box<dyn Any>> into Ref<Box<T>>将 Ref<Box<dyn Any>> 向下转换为 Ref<Box<T>> 时处理向下转换错误
【发布时间】:2020-10-11 23:34:38
【问题描述】:

我需要编写一个函数foo,它接受&amp;RefCell&lt;Box&lt;dyn Any&gt;&gt;,从RefCell 借用并返回一个向下转换的对象。向下转换的类型是在运行时选择的,但对于本例,我们假设它是 usize

use core::any::Any;
use std::cell::{RefCell, Ref};

pub fn foo<T: 'static>(cell: &RefCell<Box<dyn Any>>) -> Option<Ref<Box<T>>> {
    ???
}

pub fn main() {

    let boxed: Box<dyn Any> = Box::new(1 as usize);
    let cell = RefCell::new(boxed);

    let num = foo(&cell);
    println!("x: {}", num.unwrap());
}

我尝试像这样实现foo

// 1:
pub fn foo<T: 'static>(cell: &RefCell<Box<dyn Any>>) -> Option<Ref<Box<T>>> {
    let borrowed_cell = Ref::map(cell.borrow(), |borrow| borrow.downcast_ref::<T>().unwrap());
    Some(borrowed_cell)
}

这个版本的问题在于它假定downcast_ref 将始终有效,但我想捕捉downcast_ref 错误。 下面我尝试以可以捕获错误的方式实现foo

// 2:
pub fn foo<T: 'static>(cell: &RefCell<Box<dyn Any>>) -> Option<Ref<T>> {
    {
        cell.borrow().downcast_ref::<T>()?;
    }

    let borrowed_cell = Ref::map(cell.borrow(), |borrow| borrow.downcast_ref::<T>().unwrap());
    Some(borrowed_cell)
}

这个版本可以捕获downcast错误,但它必须调用downcast_ref两次(这可以接受,但我想知道是否有更好的方法)。当尝试只使用一次 downcast_ref 时,我遇到了终身错误。

【问题讨论】:

    标签: rust traits ref downcast refcell


    【解决方案1】:

    经过一番修改,我想出了这个解决方案。您可以在映射之前使用Any::is&lt;T&gt;()检查借用。

    pub fn foo<T: 'static>(cell: &RefCell<Box<dyn Any>>) -> Option<Ref<T>> {
        let borrowed = cell.borrow();
        
        if borrowed.is::<T>() {
            Some(Ref::map(borrowed, |x| x.downcast_ref::<T>().unwrap()))
        } else {
            None
        }
    }
    

    锈游乐场link

    【讨论】:

    • 就是这样,谢谢!与第一个问题相关的另一个问题:假设我想调用一个函数bar,就像downcast_ref一样,返回一个选项。我如何将Option 传播到Ref::map 的闭包之外,因为在这种情况下我们没有像is::&lt;T&gt; 这样的函数可以调用?
    • 找到这个crate,这似乎就是我要找的。​​span>
    猜你喜欢
    • 2021-10-08
    • 2020-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多