如何分离双精度和字符串项,得到无效的转换错误
How to segregate double and string items, getting invalid cast error
我有一个 Dictionary<string, object>
,它具有 string
和 double
的 object
值。现在我想在下面的代码中分离两种值类型。目前我收到 无效的转换错误。如何做到这一点?
namespace ConsoleApp26
{
public class Sample
{
public string SampleName;
public Dictionary<string, object> SampleValues;
}
public class SampleDivideBetweenDoubleAndStringValue
{
public string Name { get; set; }
public double DoubleValue { get; set; }
public string StringValue { get; set; }
}
class Program
{
static void Main(string[] args)
{
try
{
var samples = new Sample
{
SampleName = "test",
SampleValues = new Dictionary<string, object> {
{ "t1", 45.08 },
{ "t2", "A String Value" },
{ "t3", 83 }
}
};
var tuple = GetTuple(samples);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadKey();
}
private static Tuple<IEnumerable<SampleDivideBetweenDoubleAndStringValue>, IEnumerable<SampleDivideBetweenDoubleAndStringValue>> GetTuple(Sample samples)
{
var doubles = (from s in samples.SampleValues
select new SampleDivideBetweenDoubleAndStringValue
{
Name = samples.SampleName,
DoubleValue = (double)s.Value
});
var strings = (from s in samples.SampleValues
select new SampleDivideBetweenDoubleAndStringValue
{
Name = samples.SampleName,
StringValue = (string)s.Value
});
return new Tuple<
IEnumerable<SampleDivideBetweenDoubleAndStringValue>,
IEnumerable<SampleDivideBetweenDoubleAndStringValue>>(doubles, strings);
}
}
}
您想要字符串的键:
private static Tuple<IEnumerable<SampleDivideBetweenDoubleAndStringValue>, IEnumerable<SampleDivideBetweenDoubleAndStringValue>> GetTuple(Sample samples)
{
var doubles = (from s in samples.SampleValues
select new SampleDivideBetweenDoubleAndStringValue
{
Name = samples.SampleName,
DoubleValue = (double)s.Value
});
var strings = (from s in samples.SampleValues
select new SampleDivideBetweenDoubleAndStringValue
{
Name = samples.SampleName,
StringValue = (string)s.Key
});
return new Tuple<IEnumerable<SampleDivideBetweenDoubleAndStringValue>, IEnumerable<SampleDivideBetweenDoubleAndStringValue>>(doubles, strings);
}
但是您根本不需要强制转换这些值。在 Dictionary 中,键是字符串,值是双精度值,无需转换。
编辑
我没有看到它是 。瓦西里是对的。也许我应该删除我的答案,但在我阅读完整的问题之前,我会教自己不要回答。
您可以使用 Where
方法按类型过滤值,就像那样(我使用了 lambda 语法)
private static Tuple<IEnumerable<SampleDivideBetweenDoubleAndStringValue>, IEnumerable<SampleDivideBetweenDoubleAndStringValue>> GetTuple(Sample samples)
{
var doubles = samples.SampleValues.Where(s => s.Value is double).Select(s => new SampleDivideBetweenDoubleAndStringValue
{
Name = samples.SampleName,
DoubleValue = (double)s.Value
});
var strings = (samples.SampleValues.Where(s => s.Value is string).Select(s => new SampleDivideBetweenDoubleAndStringValue
{
Name = samples.SampleName, StringValue = (string) s.Value
}));
return new Tuple<IEnumerable<SampleDivideBetweenDoubleAndStringValue>, IEnumerable<SampleDivideBetweenDoubleAndStringValue>>(doubles, strings);
}
对于示例中的查询语法,您可以简单地使用
var doubles = from s in samples.SampleValues
where s.Value is double
select new SampleDivideBetweenDoubleAndStringValue
{
Name = samples.SampleName,
DoubleValue = (double)s.Value
};
var strings = from s in samples.SampleValues
where s.Value is string
select new SampleDivideBetweenDoubleAndStringValue
{
Name = samples.SampleName,
StringValue = (string)s.Value
};
由于 Linq
使用延迟执行,因此只有在迭代 IEnumerable
后才会显示示例中的无效转换异常。 83
值还有一个不清楚的地方,因为它是一个整数
您可以在投射前检查对象的类型:
var doubles = (from s in samples.SampleValues
where s.Value is double
select new SampleDivideBetweenDoubleAndStringValue
{
Name = samples.SampleName,
DoubleValue = (double)s.Value
});
// same for `string`
或者您可以使用 as
:
var sampleValues = (from s in samples.SampleValues
select new SampleDivideBetweenDoubleAndStringValue
{
Name = samples.SampleName,
DoubleValue = s.Value as double? ?? 0,
StringValue = s.Value as string
});
数据结构的主要问题是你 不仅 string
和 double
还有 int
:
var SampleValues = new Dictionary<string, object> {
{ "t1", 45.08 }, // boxed double value
{ "t2", "A String Value" }, // string value
{ "t3", 83 }, // <- N.B. this is boxed int (83), not double (83.0) value
};
Casting boxed int
into double
throws exception :
object o = 83; // int value (83) which is boxed into object
double d = (double) o; // <- Exception will be thrown here (invalid cast)
请注意,转换 可以:
object o = 83;
double d = Convert.ToDouble(o); // d == 83.0
因此您可以尝试过滤掉 String
项然后Convert
所有其余的(double
和int
值) 变成 double
;在你的情况下:
var doubles = samples
.SampleValues
.Where(pair => (pair.Value != null) && !(pair.Value is string)) // not string value
.Select(pair => new {
Name = samples.Name,
Value = Convert.ToDouble(pair.Value), // which we convert to double
});
var strings = samples
.SampleValues
.Where(pair => pair.Value is string)
.Select(pair => new {
Name = samples.Name,
Value = Convert.ToString(pair.Value),
});
我有一个 Dictionary<string, object>
,它具有 string
和 double
的 object
值。现在我想在下面的代码中分离两种值类型。目前我收到 无效的转换错误。如何做到这一点?
namespace ConsoleApp26
{
public class Sample
{
public string SampleName;
public Dictionary<string, object> SampleValues;
}
public class SampleDivideBetweenDoubleAndStringValue
{
public string Name { get; set; }
public double DoubleValue { get; set; }
public string StringValue { get; set; }
}
class Program
{
static void Main(string[] args)
{
try
{
var samples = new Sample
{
SampleName = "test",
SampleValues = new Dictionary<string, object> {
{ "t1", 45.08 },
{ "t2", "A String Value" },
{ "t3", 83 }
}
};
var tuple = GetTuple(samples);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadKey();
}
private static Tuple<IEnumerable<SampleDivideBetweenDoubleAndStringValue>, IEnumerable<SampleDivideBetweenDoubleAndStringValue>> GetTuple(Sample samples)
{
var doubles = (from s in samples.SampleValues
select new SampleDivideBetweenDoubleAndStringValue
{
Name = samples.SampleName,
DoubleValue = (double)s.Value
});
var strings = (from s in samples.SampleValues
select new SampleDivideBetweenDoubleAndStringValue
{
Name = samples.SampleName,
StringValue = (string)s.Value
});
return new Tuple<
IEnumerable<SampleDivideBetweenDoubleAndStringValue>,
IEnumerable<SampleDivideBetweenDoubleAndStringValue>>(doubles, strings);
}
}
}
您想要字符串的键:
private static Tuple<IEnumerable<SampleDivideBetweenDoubleAndStringValue>, IEnumerable<SampleDivideBetweenDoubleAndStringValue>> GetTuple(Sample samples)
{
var doubles = (from s in samples.SampleValues
select new SampleDivideBetweenDoubleAndStringValue
{
Name = samples.SampleName,
DoubleValue = (double)s.Value
});
var strings = (from s in samples.SampleValues
select new SampleDivideBetweenDoubleAndStringValue
{
Name = samples.SampleName,
StringValue = (string)s.Key
});
return new Tuple<IEnumerable<SampleDivideBetweenDoubleAndStringValue>, IEnumerable<SampleDivideBetweenDoubleAndStringValue>>(doubles, strings);
}
但是您根本不需要强制转换这些值。在 Dictionary
编辑
我没有看到它是
您可以使用 Where
方法按类型过滤值,就像那样(我使用了 lambda 语法)
private static Tuple<IEnumerable<SampleDivideBetweenDoubleAndStringValue>, IEnumerable<SampleDivideBetweenDoubleAndStringValue>> GetTuple(Sample samples)
{
var doubles = samples.SampleValues.Where(s => s.Value is double).Select(s => new SampleDivideBetweenDoubleAndStringValue
{
Name = samples.SampleName,
DoubleValue = (double)s.Value
});
var strings = (samples.SampleValues.Where(s => s.Value is string).Select(s => new SampleDivideBetweenDoubleAndStringValue
{
Name = samples.SampleName, StringValue = (string) s.Value
}));
return new Tuple<IEnumerable<SampleDivideBetweenDoubleAndStringValue>, IEnumerable<SampleDivideBetweenDoubleAndStringValue>>(doubles, strings);
}
对于示例中的查询语法,您可以简单地使用
var doubles = from s in samples.SampleValues
where s.Value is double
select new SampleDivideBetweenDoubleAndStringValue
{
Name = samples.SampleName,
DoubleValue = (double)s.Value
};
var strings = from s in samples.SampleValues
where s.Value is string
select new SampleDivideBetweenDoubleAndStringValue
{
Name = samples.SampleName,
StringValue = (string)s.Value
};
由于 Linq
使用延迟执行,因此只有在迭代 IEnumerable
后才会显示示例中的无效转换异常。 83
值还有一个不清楚的地方,因为它是一个整数
您可以在投射前检查对象的类型:
var doubles = (from s in samples.SampleValues
where s.Value is double
select new SampleDivideBetweenDoubleAndStringValue
{
Name = samples.SampleName,
DoubleValue = (double)s.Value
});
// same for `string`
或者您可以使用 as
:
var sampleValues = (from s in samples.SampleValues
select new SampleDivideBetweenDoubleAndStringValue
{
Name = samples.SampleName,
DoubleValue = s.Value as double? ?? 0,
StringValue = s.Value as string
});
数据结构的主要问题是你 不仅 string
和 double
还有 int
:
var SampleValues = new Dictionary<string, object> {
{ "t1", 45.08 }, // boxed double value
{ "t2", "A String Value" }, // string value
{ "t3", 83 }, // <- N.B. this is boxed int (83), not double (83.0) value
};
Casting boxed int
into double
throws exception :
object o = 83; // int value (83) which is boxed into object
double d = (double) o; // <- Exception will be thrown here (invalid cast)
请注意,转换 可以:
object o = 83;
double d = Convert.ToDouble(o); // d == 83.0
因此您可以尝试过滤掉 String
项然后Convert
所有其余的(double
和int
值) 变成 double
;在你的情况下:
var doubles = samples
.SampleValues
.Where(pair => (pair.Value != null) && !(pair.Value is string)) // not string value
.Select(pair => new {
Name = samples.Name,
Value = Convert.ToDouble(pair.Value), // which we convert to double
});
var strings = samples
.SampleValues
.Where(pair => pair.Value is string)
.Select(pair => new {
Name = samples.Name,
Value = Convert.ToString(pair.Value),
});