C#に関する難しい質問







C#でのコミック購入のトリッキーな質問に注目したいと思います。

私は抵抗できず、少しクラシックを投稿することにしました。

セレクション内のいくつかの質問は、誰かにとっては単純すぎるように見えるかもしれませんが、原則として、それらは小さなキャッチを持っています。 簡単な質問に答えることができます。 言語を勉強する人に役立ちます。

興味のある方は、カットをお願いします!



1次のコードを実行した結果はどうなりますか?



static String str; static DateTime time; static void Main(string[] args) { Console.WriteLine(str == null ? "str == null" : str); Console.WriteLine(time == null ? "time == null" : time.ToString()); Console.ReadLine(); }
      
      





答え
str == null

1/1/0001 12:00:00 AM

両方の変数は初期化されていませんが、stringは参照/参照型(より正確には、不変型であり、値型のセマンティクスを持つ参照型を意味します)、DateTimeは値型/値型です。 初期化されていないDateTimeタイプのデフォルト値は、1年1月1日の12:00です。





2継承で遊びましょう。 画面には何が表示されますか?



  class A { public void abc(int q) { Console.WriteLine("abc  A"); } } class B : A { public void abc(double p) { Console.WriteLine("abc  B"); } } static void Main(string[] args) { int i = 5; B b = new B(); b.abc(i); Console.ReadLine(); }
      
      





答え
Bのabc





3同様の質問。 結果はどうなりますか?



  class P { } class Q : P { } class A { public void abc(Q q) { Console.WriteLine("abc  A"); } } class B : A { public void abc(P p) { Console.WriteLine("abc  B"); } } static void Main(string[] args) { B b = new B(); b.abc(new Q()); Console.ReadLine(); }
      
      





答え
Bのabc

ここでのすべては、前の例と比べてもう少し明白です。





4多型の理解に関する典型的な「離婚」。 主なことは、忘れないことと、見失わないことです。

次のコードを実行した結果はどうなりますか?



  class Program { static void Main(string[] args) { MyClassB b = new MyClassB(); MyClassA a = b; a.abc(); Console.ReadLine(); } } class MyClassA { public MyClassA() { Console.WriteLine("constructor A"); } public void abc() { Console.WriteLine("A"); } } class MyClassB:MyClassA { public MyClassB() { Console.WriteLine("constructor B"); } public void abc() { Console.WriteLine("B"); } }
      
      





答え
コンストラクターA

コンストラクターB

A

クラスBが初期化されると、クラスAのデフォルトコンストラクターが実行され、次にクラスBのコンストラクターが実行されます。タイプAの変数をbに割り当てた後、クラスBのインスタンスを取得します。 Bはabcメソッドの述語を指定せず、クラスAからabcを非表示にします。この例は完全に正しいわけではなく、新しい述語が必要であるため、クラスBのabc()が強調されます。





5次のようなクラスがあります:



  public class Point { public int X { get; set; } public int Y { get; set; } public Point(int xPos, int yPos) { X = xPos; Y = yPos; } }
      
      





そして、クラスの3つのインスタンスがあります。 このような3番目のインスタンスの初期化は機能しますか? そうでない場合、何をする必要がありますか?



  Point ptOne = new Point(15, 20); Point ptTwo = new Point(40, 50); Point ptThree = ptOne + ptTwo;
      
      





答え
もちろん、例はうまくいきません。 このコードを機能させるには、Pointクラスに演算子オーバーロードを追加します。 たとえば、次のように:



  public static Point operator +(Point p1, Point p2) { return new Point(p1.X + p2.X, p1.Y + p2.Y); }
      
      









6次のコードの結果はどうなりますか?



  string result; private async void btnStart_Click(object sender, RoutedEventArgs e) { SaySomething(); txtSomeTextBlock.Text = result; } async System.Threading.Tasks.Task<string> SaySomething() { await System.Threading.Tasks.Task.Delay(1000); result = "Hello world!"; return result; }
      
      





答え
「Hello world!」ではなく、空の文字列が表示されます。 タスクSaySomething()は待機なしで呼び出されたため、SaySomethingは最初の待機、つまり行まで同期的に実行されます



 await System.Threading.Tasks.Task.Delay(1000);
      
      





その後、実行はbtnStartClickに戻ります。 SaySomething()を呼び出すときにawaitを使用すると、結果が期待され、「Hello world!」というテキストが表示されます。





7 「知っておくべき」のカテゴリからの質問。 次のコードを実行した結果はどうなりますか?



  delegate void SomeMethod(); static void Main(string[] args) { List<SomeMethod> delList = new List<SomeMethod>(); for (int i = 0; i < 10; i++) { delList.Add(delegate { Console.WriteLine(i); }); } foreach (var del in delList) { del(); } }
      
      





答え
プログラムは、10を10回表示します。

デリゲートが10回追加されました。 そして、変数iへのリンクが取得されました。 値ではなくリンク。 これが、デリゲートを呼び出すときに、変数iの最後の値が取得される理由です。 これは典型的な閉鎖です。





8次のコードで画面には何が表示されますか?



  static bool SomeMethod1() { Console.WriteLine(" 1"); return false; } static bool SomeMethod2() { Console.WriteLine(" 2"); return true; } static void Main(string[] args) { if (SomeMethod1() & SomeMethod2()) { Console.WriteLine(" if "); } }
      
      





答え
方法1

方法2

SomeMethod1がfalseを返すため、ifブロックは実行されません。 ただし、論理演算子&が使用されるため、2番目の条件SomeMethod2がチェックされます。 より使い慣れた演算子&&が使用された場合、最初のメソッドの値のみがチェックされます。





9もう1つの簡単な(ひげを生やした)質問。 次のコードを実行した結果はどうなりますか?



  double e = 2.718281828459045; object o = e; // box int ee = (int)o;
      
      





答え
このコードは機能せず、最後の行に例外をスローします。 次のキャスト(キャストまたは明示的な変換の表現)はエラーを引き起こさないように見えますが、数値の小数部分のみが失われます。



  double e = 2.718281828459045; int ee = (int)e;
      
      





ただし、ボックス化解除では、オブジェクトに要求された型の値が含まれているかどうかを確認します。 そして、このチェックの後のみ、値が変数にコピーされます。

そして、これはエラーなしでボックス化解除を行う次のものです



  int ee = (int)(double)o;
      
      





また、次のコードは、最初にオブジェクトoを動的な型にキャストし、次にキャストせずにボックス化解除ではなくキャストを実行します。



  int ee = (int)(o as dynamic);
      
      





ただし、次のコードと同等です。



  int ee = (int)(o is dynamic ? (dynamic)o : (dynamic)null);
      
      





結果は最初の例とほぼ同じになります。



  int ee = (int)(dynamic)o;
      
      





それは新しいトリックのように思えますが。





10このコードの実行の結果、何が起こりますか?



  float q = float.MaxValue; float w = float.MaxValue; checked { float a = q * w; Console.WriteLine(a.ToString()); }
      
      





答え
画面が表示されます:

無限大

floatとdoubleは整数型ではないため、checkedを使用した場合、オーバーフローは発生しません。 ただし、int、byte、short、またはlongを使用すると、エラーが発生します。 Uncheckedは、非組み込みタイプでも機能しません。 例:



  decimal x = decimal.MaxValue; decimal y = decimal.MaxValue; unchecked { decimal z = x * y; Console.WriteLine(z.ToString()); }
      
      





System.OverflowExceptionをスローします





11引き続き小数タイプで遊ぶことができます。 何かが表示された場合、それは何ですか?



  int x = 5; decimal y = x / 12; Console.WriteLine(y.ToString());
      
      





答え
xは10進数型にキャストするには遅すぎるため、この例では0が出力されます。 xは整数型であるため、5を12で除算すると1未満の数値が得られます。これは、整数のゼロであることを意味します。 正しい結果は次の行を印刷します。



  decimal y = (decimal)x / 12;
      
      









12次のコードを実行した結果、何が起こりますか:



  double d=5.15; d = d / 0; float f = 5.15f; f = f / 0; decimal dc = 5.12m; dc = dc / 0;
      
      





答え
double型とfloat型を0で除算するとInfinityが返されますが、decimalはSystem.DivideByZeroException例外をスローします



念のため、decimal、double、floatの違いについて簡単に説明します。

10進数 (128ビットのデータ型、精度は小数点以下28〜29桁)-高精度で丸め誤差のない金融計算で使用

double (64ビットデータ型、小数点以下15〜16桁の精度)は、浮動小数点値を格納するための一般的な型です。 ほとんどの場合に使用(金融を除く)

float (32ビットのデータ型、小数点以下7桁の精度)-精度と範囲は最低ですが、パフォーマンスは最高の型。 丸め誤差が発生する可能性があります。 負荷の高い計算に使用されます。





13そのような方法があるとします:



 int SomeMethod(int x, int y) { return (x - y) * (x + y); }
      
      





このように呼び出すことは可能ですか?



 SomeMethod(y:17, x:21)
      
      





答え
はい、できます。 次のように呼び出すこともできます。



 SomeMethod(11, y:27)
      
      





しかし、これはできません。



 SomeMethod(x:12, 11)
      
      





更新:C#7.2以降、このような呼び出しを行うことが可能になる可能性があります。





14このコードの実行の結果、何が起こりますか?



  static void Main(string[] args) { int someInt; SomeMethod2(out someInt); Console.WriteLine(someInt); SomeMethod1(ref someInt); Console.WriteLine(someInt); SomeMethod(someInt); Console.WriteLine(someInt); Console.ReadLine(); } static void SomeMethod(int value) { value = 0; } static void SomeMethod1(ref int value) { value = 1; } static void SomeMethod2(out int value) { value = 2; }
      
      





答え
ひどいことは何も起こりません。 以下が表示されます。

2

1

1

最初にoutキーワードを使用してSomeMethod2を呼び出すため、初期化せずにsomeIntを渡すことができます。 SomeMethodまたはSomeMethod1を使用した場合、コンパイルエラーが発生します。

SomeMethodにはキーワードrefまたはoutがパラメーターに含まれていないため、値は参照ではなく値によってこのメソッドに渡されます。つまり、someIntは変更されません。

refおよびoutキーワードは、値が参照によって渡されることを意味します。 ただし、2番目の場合、パラメーターにはメソッドで設定された値が必要です。 この例のSomeMethod2メソッドでは、valueパラメーターに値を割り当てる必要があります。





15コードは機能しますか?



  static void Main(string[] args) { goto lalala; int i = 5; { Console.WriteLine(i); } lalala: Console.WriteLine(",  ! (="); Console.ReadLine(); }
      
      





答え
はい、それは異常に見えますが。 さようなら、残酷な世界だけが画面に表示されます

メソッド内では、括弧で囲まれたローカル領域を宣言することは完全に可能です。 この領域の変数は、それ以外では使用できません。 つまり、このようなコードはコンパイルされません。



  static void Main(string[] args) { { int i = 10; } Console.WriteLine(i); }
      
      





奇妙なことに、C#のgotoは引き続きサポートされています。 特に必要ありませんが。





16表示されるもの



  string hello = "hello"; string helloWorld = "hello world"; string helloWorld2 = "hello world"; string helloWorld3 = hello + " world"; Console.WriteLine(helloWorld == helloWorld2); Console.WriteLine(object.ReferenceEquals(helloWorld, helloWorld2)); Console.WriteLine(object.ReferenceEquals(helloWorld, helloWorld3)); Console.ReadLine();
      
      







答え
表示されます:True、True、False

これは、文字列インターンの典型的な例です。 同じ値を格納する行がメモリ内の1つのオブジェクトを表す状況。 このメカニズムにより、メモリを少し経済的に使用できます。





17 C ++のようにC#でポインターを使用することは可能ですか?



答え
安全でない修飾子で宣言されたメソッド内または安全でないブロック内で可能です



 unsafe {     int a = 15; *b = &a; Console.WriteLine(*b);     }
      
      





プロジェクトのプロパティで「安全でないコードを許可する」を指定することを忘れないでください





18逐語的な文字列とは何ですか?



答え
誰もがこれらの行が何であるかを知っており、常にそれらを使用していますが、誰もが名前を知っているわけではありません。

逐語的文字列は、@文字で始まり、エスケープシーケンスが処理されない文字列です。

ロシア語でそれらを正しく呼び出す方法-逐語的または正確には別の問題です。





ボーナス:

readonlyとconstの違いは何ですか?

クラスに静的コンストラクターを使用できますか?

キャッチせずに試してみることができますか?



All Articles