2011-03-24 10 views
1

C#でクラスのコンストラクタでメソッドを呼び出すのは良い方法ではありませんが、何か変わったことはありません。私の問題は、クラスのオブジェクトを作成するときに、オブジェクトのフィールドに乱数を割り当てる必要があるということです。私の場合はC#でクラスのコンストラクタで乱数を生成する方法

例えば

class RandomNumberHandler 
    { 
     private int randomNumber; 
     public RandomNumberHandler() 
     { 
      this.randomNumber = GenerateRandomNumber(); 
     } 

     private int GenerateRandomNumber() 
     { 
      return (new Random()).Next(3000) + 1000; 
     } 
    } 

私は4桁の番号が必要です。私は、オブジェクトを作成してそれをコンストラクタのパラメータとして渡すクラスで乱数を生成することを考えましたが、他のクラスで乱数を生成することは、強い結束を達成しようとしているため、私のクラスのために。私は大学の「高品質コード」コースでこれをやっています。私は最良のアプローチを探しています。どのようにこれを行う方法歓迎です:)

+1

コンストラクタで**構築されているオブジェクトの**仮想**(abstractを含む)メソッド**を呼び出すことは、良い習慣ではありません。メソッドの呼び出しはうまく、実際は正常です。 –

答えて

5

最初オフ:コンストラクタの非仮想メソッドを呼び出すには何も問題はありません。そこにはどこがありますか? (注:仮想のメソッドと呼んでも問題ありませんが、それは自動的なno-noではありませんが、あなたは非常に慎重に何をしているのか見守る必要があります。

GenerateRandomNumberが呼び出されるたびに、新しいRandomインスタンスを生成するのは無駄です。

class RandomNumberHandler 
{ 
    private readonly Random random = new Random(); 
    private int randomNumber; 

    public RandomNumberHandler() 
    { 
     this.randomNumber = GenerateRandomNumber(); 
    } 

    private int GenerateRandomNumber() 
    { 
     return this.random.Next(3000) + 1000; 
    } 
} 

しかし、これは別の問題を提起:あなたはそれを修正するためのフィールドに Randomインスタンスを抽出することができます GenerateRandomNumberのみ(コンストラクタ内)の各インスタンスの一生に一度呼び出された場合、それはしても意味がありません。オブジェクトごとに新しい Randomを作成します。したがって、次の論理的なステップは randomstaticにすることです。これは GenerateRandomNumberstaticになることができます(実際、それが持っている)ことを意味します

class RandomNumberHandler 
{ 
    private static readonly Random Random = new Random(); 
    private int randomNumber; 

    public RandomNumberHandler() 
    { 
     this.randomNumber = GenerateRandomNumber(); 
    } 

    private static int GenerateRandomNumber() 
    { 
     return Random.Next(3000) + 1000; 
    } 
} 
+3

高品質コードコースで推測していますか? – Mikeb

+0

誰もが知っている...これらの先生は、いつどのように物事をすべきかについての意見を課す必要があります。私はちょうどグレードの流れに常に行く。 – Pete

+0

コンストラクタで* virtual *メソッドを呼び出すにはいくつかの考慮事項があります。 –

0

RandomHandlerという名前の別のクラスの中にRandomクラスをラップするだけで、そこに結束が見られません。個人的に、私はそれが不愉快だと思います。あなたが全く新しい乱数を必要とする場合は、Random()を呼び出します。次の(3000)またはあなたのようなコンストラクタの内部に何があっても。

4

このコードは問題なく動作しますが、あなたがすぐに連続して呼び出すと「同じ」乱数が得られる可能性があります。

class RandomNumberHandler 
{ 
    private static Random random = new Random(); 
    private static object syncObj = new object(); 

    private int randomNumber; 
    public RandomNumberHandler() 
    { 
     this.randomNumber = GenerateRandomNumber(); 
    } 

    private static int GenerateRandomNumber() 
    { 
     lock(syncObj) 
      return random.Next(3000) + 1000; 
    } 
} 
+0

+1これは他の2つの回答と似ていますが、スレッドセーフな唯一の回答です。 –

+0

@ジョン:私がそれを投稿したとき、それは静的を使用していた唯一のバージョンでした;) –

0

あなたが持ち上げる場合:

あなたは、もちろん、簡単なように、(あなたが複数のスレッドを使用している場合は、スレッドの安全のためにロックして)静的乱数を使用していることを回避できましたRandom静的フィールドとしてインスタンスとGenerateRandomNumberは、静的、あなたがrandomNumberフィールドの宣言で、それを呼び出すことができます単に

class RandomNumberHandler { 
    private static Random random = new Random(); 
    private int randomNumber = GenerateRandomNumber(); 

    private static int GenerateRandomNumber() { 
    return random.Next(3000) + 1000; 
    } 
} 

以上(と読みにくく):

class RandomNumberHandler { 
    private static Random random = new Random(); 
    private int randomNumber = random.Next(3000) + 1000; 
} 

コンストラクタでメソッドを呼び出すようには見えませんが、生成されたCILを見ると、あなたがいることがわかります。

スレッドセーフについて気にしている場合は、articleをご覧ください。

関連する問題