这个代码有什么不对(也许是一个错误!) [英] What's Wrong With This Code (A bug perhaps!)

查看:57
本文介绍了这个代码有什么不对(也许是一个错误!)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

希望有人可以直截了当地解决这个问题。


我正在测试一些代码,我有一个被覆盖的方法。

方法覆盖正常工作,直到我将

中的文字0(int值)作为唯一参数传递。


好吧,有两个可能的覆盖可以使用单个

参数调用。第一个采用一个对象,第二个采用枚举

类型(SqlTypeCode参见下面的代码)。由于文字0不是一个/ b
SqlTypeCode我本来期望覆盖一个对象参数来运行

。然而,我发现是覆盖SqlTypeCode运行

而不是。


看来每当一个文字值有资格作为有效的枚举
使用
值转换为int使用c#将选择使用SqlTypeCode覆盖

而不是对象。现在,只要int类型的变量与

值一起使用,可以转换为SqlTypeCode值,就会使用对象覆盖

(预期)。


给出了什么?这是一个错误还是我只是误解了一些东西?


如果这不是一个错误,似乎这个问题可能隐藏在

灌木丛中很长一段时间,它跳出来咬你。


谢谢,

-

Gregg Walker


这里是来自控制台应用程序的代码...


使用System;

使用System.Collections.Generic ;

使用System.Text;


名称空间EnumOverrideIssue

{

class Program
{

enum SqlTypeCode

{

布尔,

字节,

Char,

DateTime,

十进制,

Int16,

Int32,

Int64,

Single,

String,

TimeSpan

}

静态对象myValue = 0;

static SqlTypeCode mySqlType = SqlTypeCode.Int32;


static void Main(string [] args)

{

mySqlTyp e = SqlTypeCode.Int32; string sqlString = ToSqlString();

Console.WriteLine(" SqlString =" + sqlString);

//传入0作为文字int

mySqlType = SqlTypeCode.Int32; sqlString = ToSqlString(0);

Console.WriteLine(" SqlString =" + sqlString); //返回''true''而不是''0'

mySqlType = SqlTypeCode.Int32; sqlString = ToSqlString((int)0);

Console.WriteLine(" SqlString =" + sqlString); //返回''true''而不是''0''

//传入0作为变量int

myValue = 0; mySqlType = SqlTypeCode.Int32; sqlString =

ToSqlString(myValue); Console.WriteLine(" SqlString =" + sqlString); //

正确返回''0''

mySqlType = SqlTypeCode.DateTime; sqlString =

ToSqlString(DateTime.Today); Console.WriteLine(" SqlString =" + sqlString);


Console.ReadLine();

}


静态字符串ToSqlString()

{

返回ToSqlString(myValue,mySqlType);

}


静态字符串ToSqlString(object dataValue)

{

返回ToSqlString(dataValue,mySqlType);

}


静态字符串ToSqlString(SqlTypeCode sqlTypeCode)

{

返回ToSqlString(myValue,sqlTypeCode);

}


静态字符串ToSqlString(对象dataValue,SqlTypeCode sqlTypeCode)

{

switch(sqlTypeCode)

{

case SqlTypeCode.Boolean:return Convert.ToBoolean(dataValue).ToString();

case SqlTypeCode.Byte:return Convert.ToByte(dataValue).ToString();

case SqlTypeCode.Char:return"''" + Convert.ToChar(dataValue).ToString()

+"''" ;;

case SqlTypeCode.DateTime:return

Convert .ToDateTime(dataValue).ToString();

case SqlTypeCode.Decimal:return Convert.ToDecimal(dataValue).ToString();

case SqlTypeCode.Int16:return Convert .ToInt16(dataValue).ToString();

case SqlTypeCode.Int32:return Convert.ToInt32(dataValue).ToString();

case SqlTypeCode.Int64:return Convert .ToInt64(dataValue).ToString();

case SqlTypeCode.Single:return Convert.ToSingle(dataValue).ToString();

case SqlTypeCode.String:return" ; '' " +

Convert.ToString(dataValue).ToString()+"''" ;;

case SqlTypeCode.TimeSpan:return

TimeSpan .Parse(dataValue.ToString())。ToString();

}


返回" NULL";

}

}

}

解决方案

BTW ......我可以强迫通过提供

作为第三个单个参数覆盖来实现这种方式。


静态字符串ToSqlString(int dataValue)

{

返回ToSqlString(dataValue,mySqlType);

}


这间接强制对象覆盖在文字整数的情况下调用而不是

SqlTypeCode覆盖在枚举定义中具有有效值的



2007年5月17日星期四16:54:00 -0700,Gregg Walker< xy *** @newsgroup.nospam>

写道:


[...]

看来每当使用符合有效枚举值的文字值转换为int时,c#将选择使用SqlTypeCode覆盖

而不是对象。现在,只要int类型的变量与

a值一起使用,可以转换为SqlTypeCode值,就会使用对象覆盖

(预期)。


给出了什么?这是一个错误还是我只是误解了什么?



我对C#来说太新了,无法解释为什么它会转换文字,但是盒子

变量。从表面上看,我同意这似乎是不一致的。

我敢打赌,虽然有一些合理的理由。


但是,在我看来,你真的不需要第三次重载

修复这个问题。如果你只是显式地转换参数(到对象),

那么这将确保你使用你期望的重载。我认为无论如何都要对重载方法进行模糊调用是个坏主意。即使编译规则是明确的,阅读代码的人也应该能够轻松地看到实际调用的是什么超载。


我也不清楚为什么不起作用的原因。 case返回true相反

的假,但我可能只是遗漏了你发布的代码中的内容。


Pete


Gregg Walker< xy *** @ newsgroup.nospamwrote:


我正在测试一些代码,我有一个方法正在覆盖。

方法覆盖正常工作,直到我将

中的文字0(int值)作为唯一参数传递。


好吧,有两个可能的覆盖可以使用单个

参数调用。第一个采用一个对象,第二个采用枚举

类型(SqlTypeCode参见下面的代码)。由于文字0不是一个/ b
SqlTypeCode我本来期望覆盖一个对象参数来运行

。然而,我发现是覆盖SqlTypeCode运行

而不是。



从0到任何枚举类型的隐式转换。


看来每当一个文字值,有资格作为有效枚举

值转换为int使用c#将选择使用SqlTypeCode覆盖

而不是对象。



嗯,根据C#规范,只有0才能在没有

警告的情况下进行转换。我相信Mono和MS编译器也会转换任何

hex文字进行转换。


我不确定为什么转换有一点都不这很有用

有时作为获得枚举值的简单方法,但我同意这是一个潜在的问题来源。


-

Jon Skeet - < sk *** @ pobox.com>
http://www.pobox.com/~skeet 博客: http://www.msmvps.com/jon.skeet

如果回复该群组,请不要给我发邮件


Hopefully someone can set me straight on this issue.

I was testing some code where I have a method that is being overriden. The
method overrides were working fine until I passed a literal 0 (int value) in
as the lone argument.

Well there are two possible overrides that could be called with a single
argument. The first one takes an object and the second one takes an enum
type (SqlTypeCode see the code below). Since a literal 0 is not a
SqlTypeCode I would have expected the override taking an object argument to
be run. However what I found was the override taking the SqlTypeCode was run
instead.

It appears that whenever a literal value that qualifies as a valid enum
value cast to int is used c# will choose to use the SqlTypeCode override
instead of the object. Now whenever a variable of type int is used with a
value that can be cast to the SqlTypeCode value the object override
(expected) is used.

What gives? Is this a bug or am I just misunderstanding something?

If this is not a bug it seems this issue could be something that hides in
the bushes for a long time until it jumps out and bites you.

Thank you,
--
Gregg Walker

Here''s the code from a console app...

using System;
using System.Collections.Generic;
using System.Text;

namespace EnumOverrideIssue
{
class Program
{
enum SqlTypeCode
{
Boolean,
Byte,
Char,
DateTime,
Decimal,
Int16,
Int32,
Int64,
Single,
String,
TimeSpan
}

static object myValue = 0;
static SqlTypeCode mySqlType = SqlTypeCode.Int32;

static void Main(string[] args)
{
mySqlType = SqlTypeCode.Int32; string sqlString = ToSqlString();
Console.WriteLine("SqlString=" + sqlString);
// Pass in 0 as literal int
mySqlType = SqlTypeCode.Int32; sqlString = ToSqlString(0);
Console.WriteLine("SqlString=" + sqlString); // Returns ''true'' instead of ''0''
mySqlType = SqlTypeCode.Int32; sqlString = ToSqlString((int)0);
Console.WriteLine("SqlString=" + sqlString); // Returns ''true'' instead of ''0''
// Pass in 0 as variable int
myValue = 0; mySqlType = SqlTypeCode.Int32; sqlString =
ToSqlString(myValue); Console.WriteLine("SqlString=" + sqlString); //
Correctly returns ''0''
mySqlType = SqlTypeCode.DateTime; sqlString =
ToSqlString(DateTime.Today); Console.WriteLine("SqlString=" + sqlString);

Console.ReadLine();
}

static string ToSqlString()
{
return ToSqlString(myValue, mySqlType);
}

static string ToSqlString(object dataValue)
{
return ToSqlString(dataValue, mySqlType);
}

static string ToSqlString(SqlTypeCode sqlTypeCode)
{
return ToSqlString(myValue, sqlTypeCode);
}

static string ToSqlString(object dataValue, SqlTypeCode sqlTypeCode)
{
switch(sqlTypeCode)
{
case SqlTypeCode.Boolean: return Convert.ToBoolean(dataValue).ToString();
case SqlTypeCode.Byte: return Convert.ToByte(dataValue).ToString();
case SqlTypeCode.Char: return "''" + Convert.ToChar(dataValue).ToString()
+ "''";
case SqlTypeCode.DateTime: return
Convert.ToDateTime(dataValue).ToString();
case SqlTypeCode.Decimal: return Convert.ToDecimal(dataValue).ToString();
case SqlTypeCode.Int16: return Convert.ToInt16(dataValue).ToString();
case SqlTypeCode.Int32: return Convert.ToInt32(dataValue).ToString();
case SqlTypeCode.Int64: return Convert.ToInt64(dataValue).ToString();
case SqlTypeCode.Single: return Convert.ToSingle(dataValue).ToString();
case SqlTypeCode.String: return "''" +
Convert.ToString(dataValue).ToString() + "''";
case SqlTypeCode.TimeSpan: return
TimeSpan.Parse(dataValue.ToString()).ToString();
}

return "NULL";
}
}
}

解决方案

BTW... I can force this to work the way I''m expecting by providing the
following as a third single argument override.

static string ToSqlString(int dataValue)
{
return ToSqlString(dataValue, mySqlType);
}

This indirectly forces the object override to be called instead of the
SqlTypeCode override in the case of literal ints that have a valid value in
the enum definition.


On Thu, 17 May 2007 16:54:00 -0700, Gregg Walker <xy***@newsgroup.nospam>
wrote:

[...]
It appears that whenever a literal value that qualifies as a valid enum
value cast to int is used c# will choose to use the SqlTypeCode override
instead of the object. Now whenever a variable of type int is used with
a value that can be cast to the SqlTypeCode value the object override
(expected) is used.

What gives? Is this a bug or am I just misunderstanding something?

I''m too new to C# to be able to explain why it casts literals, but boxes
variables. On the face of it, I agree that appears to be inconsistent.
I''ll bet there''s some reasonably good reason though.

However, it does seem to me that you don''t really need a third overload to
fix the issue. If you''d just cast the parameter explicitly (to "object"),
then that would ensure that you use the overload you expect. I think it''s
a bad idea to have ambiguous calls to overloaded methods anyway. Even if
the compiler rules are explicit, people reading the code should be able to
easily see what overload actually gets called.

I''m also not clear on why the "doesn''t work" case returns "true" instead
of "false", but I''m probably just missing something in the code you posted.

Pete


Gregg Walker <xy***@newsgroup.nospamwrote:

I was testing some code where I have a method that is being overriden. The
method overrides were working fine until I passed a literal 0 (int value) in
as the lone argument.

Well there are two possible overrides that could be called with a single
argument. The first one takes an object and the second one takes an enum
type (SqlTypeCode see the code below). Since a literal 0 is not a
SqlTypeCode I would have expected the override taking an object argument to
be run. However what I found was the override taking the SqlTypeCode was run
instead.

There''s an implicit conversion from 0 to any enum type.

It appears that whenever a literal value that qualifies as a valid enum
value cast to int is used c# will choose to use the SqlTypeCode override
instead of the object.

Well, according to the C# spec, only 0 should be converted without
warning. I believe that both the Mono and MS compilers also convert any
hex literal to be converted.

I''m not exactly sure why the conversion is there at all. It''s useful
sometimes as an easy way of getting an enum value, but I agree it''s a
potential source of problems.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too


这篇关于这个代码有什么不对(也许是一个错误!)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆