1をshortとして渡すことができるのに、int変数iを渡せないのはなぜですか?


146

最初と2番目の書き込みは機能するが、最後は機能しないのはなぜですか?3つすべてを許可して1(int)1であるか、それとも渡されたかを検出できる方法はありますか?そして、本当になぜそれが許されるのですか?2つ目は許可されていますが、最後は許可されていません。

コンパイルエラーを表示するデモ

using System;
class Program
{
    public static void Write(short v) { }
    static void Main(string[] args)
    {
        Write(1);//ok
        Write((int)1);//ok
        int i=1;
        Write(i);//error!?
    }
}

2
私もこれに悩まされています。キャストできるはずですが、intを関数呼び出しでshortにキャストする必要があります...
Mathieu Dumoulin

2
@MathieuDumoulinキャスタブルなので、キャストできます。しかし、これはロスフル変換であるため(shortに収まらない多くのintがあるため)、暗黙のキャストは不可能です(short) i。そのため、を記述する必要があります。
Abel、

回答:


186

最初の2つは定数式で、最後の1つはそうではありません。

C#仕様では、定数の場合、intからshortへの暗黙的な変換を許可していますが、他の式の場合は許可していません。定数の場合、コンパイラは値がターゲットの型に適合することを保証できますが、通常の式の場合はそうでないため、これは妥当な規則です。

このルールは、暗黙的な変換はロスレスでなければならないというガイドラインに沿っています。

6.1.8暗黙的な定数式変換

暗黙的な定数式変換では、次の変換が可能です。

  • 定数式タイプの(§7.18)はint型に変換することができsbytebyteshortushortuint、又はulong、の提供された値の定数式は、先の型の範囲内です。
  • 定数式タイプのは、long型に変換することができるulongの値設け、定数式が負ではありません。

(C#言語仕様バージョン3.0から引用)


67

切り捨ての可能性があるため、からintへの暗黙の変換はありませんshort。ただし、定数式、コンパイラーによってターゲット・タイプとして扱うことができます。

1?問題ありません。これは明らかに有効なshort値です。i?それほどではありません。short.MaxValueたとえば、ある値になる可能性があり、コンパイラーは一般的なケースではそれをチェックできません。


だから...私がどれほど明示的であるかは関係ありません...> _ <。literealが渡されたかどうか、またはint変数を検出できるかどうかはわかりますか?

@ acidzombie24あなたはできません。しかし、なぜそれをしたいのでしょうか?
アダムホールズワース

@ acidzombie24あなたはそれを検出できないと思います。あなたはできますが、テンプレート引数を使用して、その型で取得するためにリフレクションを使用しています。
Konrad Rudolph

3
@ acidzombie24実行時にリテラルを渡す方法はありません。したがって、コンパイル時にチェックするのに目を使うだけです。
ジャスティン

1
@ acidzombie24その場合、それは引数をExpression<Func<int>>?として受け入れるオプションでしょうか?次に、関数内() => 1または() => i関数内で、渡されたエンティティにキャプチャされた変数または定数値が含まれているかどうかを検査できます。
Konrad Rudolph

8

int リテラルは暗黙的に変換することができますshort。一方:

あなたは暗黙的に、より大きなストレージサイズの非リテラル数値型を変換することはできません短いです

したがって、リテラルの暗黙的な変換が許可されているため、最初の2つは機能します。


3
あなたの答えは少し間違っています。リテラルではなく、定数式を使用する必要があります。特に、2番目の例はリテラルではありません。
CodesInChaos

6

最初の2つはリテラル/定数を渡していますが、3番目の整数を渡すときに型の自動変換は行われないためです。

編集:誰かが私を倒しました!


3

非リテラル型から大きなサイズのshortへの暗黙的な変換は行われないためです。

暗黙的な変換は、定数式でのみ可能です。

public static void Write(short v) { }

integer引数として値を渡す場所short

int i=1;
Write(i);  //Which is Nonliteral here

3

コンパイラーは、なぜコードが失敗するのかを教えてくれました:

cannot convert `int' expression to type `short'

だからここにあなたが尋ねるべき質問があります:なぜこの変換は失敗するのですか?私は「c#convert int short」をググって、shortキーワードのMS C#ページに行きました:

http://msdn.microsoft.com/en-us/library/ybs77ex4(v=vs.71).aspx

このページにあるように、より大きなデータ型からの暗黙的なキャストshortはリテラルに対してのみ許可されています。コンパイラーはリテラルが範囲外であることを認識できますが、そうでない場合はそうでないため、プログラムロジックで範囲外のエラーを回避したことを再確認する必要があります。その安心感はキャストによって提供されます。

Write((short)i)

0

int-> shortから変換すると、データが切り捨てられる可能性があります。それが理由です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.