我只是做简单的int swap程序。我也刚刚学会了铸造,所以我在这个程序中尝试了。但我收到一个错误,说我应该做一个明确的演员。
我认为我不了解演员的概念。有什么问题?
static void Main(string[] args)
{
Console.WriteLine("Enter the FIRST Integer.");
string tempint1 = Console.ReadLine();
int int1 = Convert.ToInt32(tempint1);
Console.WriteLine("Enter the SECOND Integer.");
string tempint2 = Console.ReadLine();
int int2 = Convert.ToInt32(tempint2);
Console.WriteLine();
int? swapInt = null;
swapInt = (int)int1;
int1 = int2;
int2 = swapInt;
Console.WriteLine("The integers have been swapped!");
Console.WriteLine("The FIRST INTEGER is now " + int1);
Console.WriteLine("The SECOND INTEGER is now " + int2);
Console.WriteLine();
}
答案 0 :(得分:6)
int?
是名为Nullable<int>
的类型的简写。显然,int
和Nullable<int>
不是同一类型。 Nullable<int>
有一个名为Value
的属性,该属性是实际的int
。要访问Value
属性,首先应检查HasValue
属性是否为true
(就像检查引用类型是否为null
一样)。
现在是问题所在:
从int
到Nullable<int>
的隐式转换(请记住,这与int?
相同)并且该转换表示创建了新的Nullable<int>
,{ {1}}设置为HasValue
,其true
设置为初始Value
的值。因此,您可以这样做:
int
另一方面,从int a = 5
int? b = 5; // implicit conversion
int? c = a; // implicit conversion
int? d = c;
到Nullable<int>
的相反转换不会隐式存在,因为int
可能将其Nullable<int>
属性设置为{{ 1}},这意味着常规HasValue
将无法描述它,并且编译器不知道在这种情况下你想要发生什么。所以,这就是你无法做到的原因:
false
相反,你想要做这样的事情:
int
强制转换与问题无关(这只是编译器的建议,但实际上并不是你想要做的)。为了学习:强制转换只是指令编译器将一种类型的表达式视为另一种(希望是兼容的)类型的表达式,可能是通过在这两种类型之间应用转换(如果在任何地方定义了这种转换) )。
答案 1 :(得分:5)
swapInt
是一个可以为空的int及以下:
你试图将一个可以为空的int赋给一个解决问题的int:
int2 = swapInt;
如果将其更改为以下版本,则可以,
int2 = swapInt.Value;
此外,这段代码:
int? swapInt = null;
swapInt = (int)int1;
int1 = int2;
int2 = swapInt;
可以改为以下一个:
int? swapInt = int1;
int1 = int2;
int2 = swapInt.Value;
您不必将已经整数转换为int (int)int1;
<强>更新强>
我必须对您的计划发表一些意见,您可以将其纳入计划。
static void Main(string[] args)
{
// Get the users input.
Console.WriteLine("Enter the FIRST Integer.");
string a = Console.ReadLine();
Console.WriteLine("Enter the SECOND Integer.");
string b = Console.ReadLine();
// Variables, in which we will store the parsed strings that user passes.
int integerA;
int integerB;
// Try to parse the strings that user passes to create two integer numbers.
// If either parse of a or parse of b fail, then the method Int32.TryParse()
// will return false and the code in the body of if, will not be executed.
if(Int32.TryParse(a, out integerA) && Int32.TryParse(b, out integerB))
{
// Pass the integers to the methods called swap
Swap(ref integerA, ref integerB);
Console.WriteLine("The integers have been swapped!");
Console.WriteLine("The FIRST INTEGER is now " + int1);
Console.WriteLine("The SECOND INTEGER is now " + int2);
}
Console.WriteLine();
}
// This methods makes the actual swap
static void Swap(ref int a, ref int b)
{
int temp = a;
a = b;
b = temp;
}
如果你仔细阅读上面的代码,那么你会注意到我们没有使用nullables,实际上,在这种情况下我们不需要它们。
有关您的信息,C#中有一个泛型方法,可用于交换对象,无论它们是否为数字。此方法的名称为Swap
,其签名如下:
static void Swap<T>(ref T lhs, ref T rhs)
您可以使用以下方法:
Swap<int>(ref integerA, ref integerB);
有关此方法的详细信息,请查看here。
ref
代表什么?
如MSDN
中所述:
ref关键字导致参数通过引用传递,而不是通过值传递。通过引用传递的效果是方法中对参数的任何更改都会反映在调用方法中的基础参数变量中。引用参数的值始终与基础参数变量的值相同。
示例让我们有一个名为Increment
的方法:
public void Increment(int x)
{
// This will increase the value of variable x by one.
// This change is only visible insied the body of this method
// and it is not reflected outside of it.
x++;
}
如果我们定义了如下方法:
public void Increment(ref int x)
{
x++;
}
x
的值的变化也会在名为Increment
的方法体外显现。
为什么会这样?
因为在第一种情况下,我们传递了x
中存储的值的副本,而在第二种情况下,我们没有传递副本< / strong>这个值。因此,第二种情况的任何变化也将反映在名为Incerement
的方法体外。
答案 2 :(得分:1)
问题是从int?
到int
存在无隐式转化。由于int?
可以为null,编译器不允许这样做,它希望您明确地执行转换:
int2 = (int) swapInt;
通过这样做,你告诉编译器&#34; 我知道我在做什么。&#34;,如果swapInt
为空,这将抛出异常在运行时。
答案 3 :(得分:-1)
你的问题就在这一行
int2 = swapInt;
int2
是integer
,swapInt
是nullable int
或null?
。您不能这样分配,因为编译器无法直接将null?
转换为null
。因此错误
无法隐式转换类型&#39; int?&#39; to&#39; int&#39;。存在显式转换(您是否错过了演员?)
当它无法执行此操作时,它会要求您转换它。
所以改变
int2 = swapInt;
到
if (swapInt.HasValue)
int2 = swapInt.Value;
可空类型
像int
这样的值类型不能为空。可空类型是存储值类型的类型,可以为null。
要从中提取价值,请先检查它们是否有价值。这样做是检查HasValue
。它返回一个布尔值,如果为真,我们使用swapInt.Value
提取值。
您可以像(int)swapInt
一样进行投射,但如果它没有任何值,它将抛出异常。
您可以投出或获取其价值。两者的性能与cast相同,是Value属性的语法糖。
答案 4 :(得分:-1)
swapInt
是可以为空的类型,方法GetValueOrDefault
如果不为null则返回值,否则返回基础类型的默认值
int2 = swapInt.GetValueOrDefault()