Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a Rust equivalent to `dynamic` in C#?

Tags:

dynamic

rust

Can the following C# code be translated to Rust?

dynamic x = 109;
x = "Hi";

I'm asking for a general dynamic type to allow creating an array of dynamic values. For example:

var l = new dynamic[2];
l[0] = 102;
l[1] = "Hi";
like image 488
TuxCrafting Avatar asked Mar 12 '23 19:03

TuxCrafting


2 Answers

One option is to use a vector of Any (link to beta because the stable docs is not showing the methods defined for Any, but they are stable):

use std::any::Any;

fn main() {
    let mut v: Vec<Box<Any>> = vec![];
    v.push(Box::new(102usize));
    v.push(Box::new("Hi"));

    for item in &v {
        // to do an operation, it is necessary to downcast to
        // a concrete type
        if let Some(x) = item.downcast_ref::<usize>() {
            println!("num = {:?}", x)
        }
    }
}

Note that, contrary to dynamic in C#, that is assumed to support any operation, a value of type Any (Box<Any>) only support the operations defined in Any (Box<Any> and Any). A downcast is necessary to call any method of the concrete type.


I think that it is not possible to have a type like dynamic of C# in Rust. To support calling any method on a dynamic value, it is necessary to have (complete) runtime reflection support, and Rust does not provide it.

If you know the methods that will be called, then the best option is to define a trait and use Box<Trait> (Any is not necessary in this case).

like image 65
malbarbo Avatar answered Mar 23 '23 05:03

malbarbo


Not directly. You can just create a new binding for x:

fn main() {
    let x = 109;
    let x = "Hi";
}

Depending on your use case, you might be able to use a generic bounded by a trait or a trait object to achieve similar goals:

use std::fmt::Display;

fn main() {
    let mut x: Box<Display> = Box::new(109);
    x = Box::new("Hi");
}

However, the C# docs state:

At compile time, an element that is typed as dynamic is assumed to support any operation.

This is not true for a trait object; a trait object only can be used for the explicit methods in the trait. I have not found this to be a significant hurdle in the code I have written. Generally, there's a fixed number of methods that I want to call so it's possible to map those to a trait. In other cases, I can provide a generic type to allow the user to specify a type that fits their case.

like image 43
Shepmaster Avatar answered Mar 23 '23 04:03

Shepmaster