当且仅当a
和b
不是None
时,才会执行操作。我不想创建复杂结构的副本,这就是struct X
未实现Clone
的原因。
use std::sync::{Arc, Mutex};
use std::cell::RefCell;
#[derive(Debug)]
struct X {
d: u32,
}
struct Foo {
a: Option<X>,
b: Option<u32>,
c: u32,
}
fn main() {
let smart_ptr = Arc::new(Mutex::new(RefCell::new(Foo {
a: Some(X { d: 1 }),
b: Some(2),
c: 3,
})));
{
let lock = smart_ptr.lock().unwrap();
let foo = lock.borrow();
if let (Some(ref a), Some(b)) = (foo.a, foo.b) {
println!("a: {:?}, b: {}", a, b);
}
}
}
如果我尝试编译此代码,我会得到:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:25:42
|
25 | if let (Some(ref a), Some(b)) = (foo.a, foo.b) {
| ^^^ cannot move out of borrowed content
如何在没有编译错误的情况下修复if
语句以获得我想要的内容?
答案 0 :(得分:5)
使用较小的例子:
struct Foo {
a: Option<String>,
b: Option<String>,
}
fn main() {
let foo = &Foo {
a: Some("hi".into()),
b: Some("world".into()),
};
if let (Some(a), Some(b)) = (foo.a, foo.b) {
println!("a: {}, b: {}", a, b);
}
}
您可以使用Option::as_ref
在引用上执行与the previous answer相同类型的匹配:
if let (Some(a), Some(b)) = (foo.a.as_ref(), foo.b.as_ref()) {
println!("a: {}, b: {}", a, b);
}
答案 1 :(得分:3)
您需要告诉if let
语句仅引用a
和b
引用foo.a
和foo.b
,否则if let
会移动一些foo.a
从借来的价值中取出的部分。禁止这样做有两个原因:
a
移到foo.a
,&#34;偷走&#34;来自贷方的结构,然后foo
中的值将不再有效,使Foo::a
也无效。一种解决方案是通过Foo::b
复制值clone()
和if let (&Some(ref a), &Some(b)) = (&foo.a, &foo.b) {
println!("a: {:?}, b: {}", a, b);
}
,这是 - 如您所述 - 不需要且性能明智不理想,特别是因为它意味着深层复制
我没有复制就让它工作了:
using System;
using System.Windows.Forms;
using System.Xml.Linq;
using System.IO;
namespace SplitXmlFile_41385730
{
public partial class Form1 : Form
{
public static string incomingXML = @"M:\StackOverflowQuestionsAndAnswers\SplitXmlFile_41385730\SplitXmlFile_41385730\Samples\data.xml";
public static string outgoingXML = @"M:\StackOverflowQuestionsAndAnswers\SplitXmlFile_41385730\SplitXmlFile_41385730\Samples\data_out.xml";
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
XElement theincomingDoc = new XElement(XDocument.Load(incomingXML).Root);//the incoming XML
//store the header of your files
XElement header = new XElement(theincomingDoc);
header.Elements("node6").Remove();//remove these nodes since they need to be parked in their own file
int fileCounter = 0;//hold on, we'll use this in a moment
//loop through the different nodes you're interested in
foreach (XElement item in theincomingDoc.Elements("node6"))
{
fileCounter++;//increment the file counter
string outfilename = Path.GetDirectoryName(outgoingXML) + "\\" + Path.GetFileNameWithoutExtension(outgoingXML) + fileCounter + Path.GetExtension(outgoingXML);//come up with a file name that suits your needs
XDocument newoutfile = new XDocument("", new XElement(header));//create a new document and start it with the header we already stored
newoutfile.Element("node1").Add(item);//now add the node you need separated
newoutfile.Save(outfilename, SaveOptions.None);//save the file
}
}
}
}
答案 2 :(得分:3)
您可以destructure Foo
而不是创建元组:
if let Foo { a: Some(ref a), b: Some(b), .. } = *foo {
println!("a: {:?}, b: {}", a, b);
}