From/Into & TryFrom
Implemente From e TryFrom para conversões explícitas e descobríveis entre tipos. Prefira-os em vez de as ad-hoc e "sopa" de nomes de construtores.
Receita
impl From<u64> for UserId {
fn from(id: u64) -> Self { UserId(id) }
}
let id: UserId = 42.into();
impl TryFrom<String> for Email {
type Error = ParseError;
fn try_from(s: String) -> Result<Self, Self::Error> { Email::parse(s) }
}Quando usar isso: Conversões de fronteira, newtypes, análise de entrada externa.
Exemplo de Trabalho
struct Meters(f64);
struct Feet(f64);
impl From<Feet> for Meters {
fn from(f: Feet) -> Self { Meters(f.0 * 0.3048) }
}
impl TryFrom<&str> for UserId {
type Error = std::num::ParseIntError;
fn try_from(s: &str) -> Result<Self, Self::Error> {
Ok(UserId(s.parse()?))
}
}O que isso demonstra:
Intoimplementado automaticamente quandoFromexiste- Análise falível usa
TryFrom+? - Conversões são simétricas e fáceis de buscar
- Diretrizes de API preferem
Fromem vez de métodosinto_foo
Mergulho Profundo
Implemente From no tipo de destino. Encadeie com ? em manipuladores: let id = UserId::try_from(path_segment)?;. Evite From que pode falhar; use TryFrom em vez disso.
Armadilhas
- From com Perda de Dados - truncamento silencioso. Correção: apenas conversões infalíveis em
From; useTryFrompara validação. - Recursão de From - loop infinito. Correção: apenas uma direção ou tipos distintos.
- Regra do Orphan - não é possível
impl From<Foreign> for Foreign. Correção: wrapper newtype. - Into Ambíguo - múltiplos destinos. Correção: use turbofish
UserId::from(x). - Casts
aspara enums - inseguro para valores. Correção:TryFrom<u8>para formatos de comunicação.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
parse() inerente | análise de string de tipo único | trait padrão entre tipos |
as cast primitivo | regras de alargamento numérico claras | validação de domínio |
map em Option | transformação leve | conversão de API pública |
FAQs
From vs new custom?
new para semântica de domínio; TryFrom ao converter de representação externa.
serde com TryFrom?
Desserializar para DTO e depois TryInto tipo de domínio no manipulador.
From blanket?
Evite impls conflitantes; siga as regras do orphan.
Into em genéricos?
fn f<T: Into<UserId>>(t: T) aceita muitas fontes.
tipo de erro TryFrom?
Use enum de erro de domínio, não String.
conversões de ref?
TryFrom<&str> é comum; TryFrom<String> de propriedade evita alocação extra quando já é de propriedade.
clippy cast?
Prefira TryFrom sobre as para entrada do usuário.
testar roundtrip?
assert_eq!(x, T::from(U::from(x))) quando a bijeção se mantém.
tipo de crate estrangeiro?
Newtype e depois From/TryFrom no newtype.
documentar conversões?
Exemplos do Rustdoc mostrando from, into, try_from.
Relacionado
- O Padrão Newtype - tipos distintos
- Diretrizes de API Rust
- Análise e Conversão
- Regras de Tratamento de Erros
Versões da Pilha: Esta página foi escrita para Rust 1.97.0 (edição 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4 e Polars 0.46+.