質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

2回答

2664閲覧

C# プログラムがどういうプロセスで動くのか知りたい

oftolisan

総合スコア7

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

1グッド

0クリップ

投稿2017/08/13 15:07

###前提・実現したいこと

Visual Studio 2015 と教則本を使ってC#プログラミングの勉強をしている超初心者です。

今とある教則本の、WPFアプリケーション(顧客住所録)を、全て写経し、デバッグモードでエラーが無くアプリが正しく起動し、動作すること、までを確認したところです。

次のステップとして、勉強のために、ウオッチウインドウに「自動変数」と「呼び出し履歴」を表示させて、最初からステップイン実行して見ることで、プログラムがどういうプロセスで動くのかを勉強しようと思っています。

そこで、いきなり壁にぶちあたったので質問させて下さい。

得にブレークポイントは設定せず、最初から、ステップイン実行(F11キー押下)を始めると

先ず

MainWindow.xaml.cs の

public partial class MainWindow : Window クラスの

public MainWindow() コンストラクタ { DataContextChanged += MainWindow_DataContextChanged; InitializeComponent(); }

が実行され(黄色くハイライトされ)、「InitializeComponent();」の部分で、ステップイン実行(F11キー押下)すると次は、

public partial class MainViewModel : CustomerViewModel クラスの

public ObservableCollection<CustomerViewModel> Items
{ get; private set; } = new ObservableCollection<CustomerViewModel>();

に処理が移り、次にステップイン実行(F11キー押下)すると、同じクラス内の下記コードに
処理が移りました。

private string _keyword = "";

public MainViewModel() { Clear(); }

###分からないこと

①なぜ、MainWindow(){} の InitializeComponent(); からMainViewModel クラスの Itemsプロパティに処理が飛んだ(?)のか、

②その後、なぜ、同クラス内のフィールド変数 _keyword の宣言に飛んだのか

③その後、なぜ、同クラス内の MainViewModel() のコンストラクタに飛んだのか

が分からないので、ご教示いただけませんでしょうか。なにとぞよろしくお願いいたします。

質問の仕方、必要な情報などが間違っていましたら、お叱り、ご指摘頂ければ幸いです。

###補足情報

  1. MainViewModel と 2) CustomerViewModel のコードを貼ります。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Input; using System.Collections.ObjectModel; using System.Data.Entity.Infrastructure; namespace AddClassLibrary { public partial class MainViewModel : CustomerViewModel { public MainViewModel() { Clear(); } public string Title => "ひと目でわかる顧客情報"; public Action<string> ShowErrorMessage { private get; set; } public Func<string, bool> ShowYesNoMessage { private get; set; } public Action ShowAboutWindow { private get; set; } public string DebugConnectionString { get { return AddDbContext.DebugConnectionString; } set { AddDbContext.DebugConnectionString = value; } } public string ReleaseConnectionString { get { return AddDbContext.ReleaseConnectionString; } set { AddDbContext.ReleaseConnectionString = value; } } public string HelpUri { get; set; } public ObservableCollection<CustomerViewModel> Items { get; private set; } = new ObservableCollection<CustomerViewModel>(); private CustomerViewModel _item; public CustomerViewModel Item { get { return _item; } set { if (_item == value) return; _item = value; SetProperties(value); OnPropertyChanged(nameof(Item)); } } private string _keyword = ""; public string Keyword { get { return _keyword; } set { if (_keyword == value) return; _keyword = value; OnPropertyChanged(nameof(Keyword)); } } private void Clear() { Item = null; Items.Clear(); CustomerViewModel m = new CustomerViewModel { Id = 0, Name = "(新規)", PostCode = "0" }; Items.Add(m); Item = m; } private void ExecuteSearchCommand() { Clear(); foreach (Customer x in MainModel.GetItems(Keyword)) { CustomerViewModel item = new CustomerViewModel(x); Items.Add(item); } OnPropertyChanged(nameof(Items)); } private void ExecuteClearCommand() { Keyword = ""; Clear(); OnPropertyChanged(nameof(Items)); } private bool CanExecuteUpdateCommand() => !HasErrors; private void ExecuteUpdateCommand() { Action add = () => { Customer m = new Customer(); m.SetProperties(Customer); m = MainModel.AddItem(m); CustomerViewModel item = new CustomerViewModel(m); Items.Insert(1, item); Item = item; }; Action update = () => { Customer m = Customer; m = MainModel.UpdateItem(m); Item.SetProperties(m); SetProperties(Item); }; Action a = (Item.Id == 0) ? add : update; ExecuteUpdateItem(a); } private bool CanExecuteDeleteCommand() => !HasErrors && Id != 0; private void ExecuteDeleteCommand() { if (!ShowYesNoMessage("選択中の顧客情報を削除して良いですか?")) return; Action delete = () => { MainModel.DeleteItem(Customer); CustomerViewModel m = Item; Item = null; Items.Remove(m); Item = Items[0]; }; ExecuteUpdateItem(delete); } private void ExecuteAboutCommand() => ShowAboutWindow(); private void ExecuteHelpCommand() { try { System.Diagnostics.Process.Start(HelpUri); } catch (Exception ex) { ShowErrorMessage(ex.Message); } } private void ExecuteUpdateItem(Action action) { try { action(); OnPropertyChanged(nameof(Items)); } catch(DbUpdateConcurrencyException ex) { ShowErrorMessage( "他のユーザーによって変更されています。再度、検索しなおして下さい\n\n" + ex.Message); } catch(Exception ex) { ShowErrorMessage("データの更新または削除に失敗しました\n\n" + ex.Message); } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AddClassLibrary { public class CustomerViewModel : ModelBase<Customer> { public CustomerViewModel() { } public CustomerViewModel(Customer model) { SetProperties(model); } public void SetProperties(CustomerViewModel source) { if (source == null) return; Id = source.Id; Name = source.Name; Kana = source.Kana; Address = source.Address; TelNumber = source.TelNumber; Memo = source.Memo; TimeStamp = source.TimeStamp; PostCode = source.PostCode; } public void SetProperties(Customer source) { if (source == null) return; Id = source.Id; Name = source.Name; Kana = source.Kana; Address = source.Address; TelNumber = source.TelNumber; Memo = source.Memo; TimeStamp = source.TimeStamp; PostCode = source.PostCode.ToString(); } public Customer Customer => _model; private int _Id; public int Id { get { return _Id; } set { if (_Id == value) return; _Id = value; if (ValidationValue(nameof(Id), value)) { _model.Id = value; } OnPropertyChanged(nameof(Id)); OnPropertyChanged(nameof(Error)); } } private string _Name; public string Name { get { return _Name; } set { if (_Name == value) return; _Name = value; if (ValidationValue(nameof(Name), value)) { _model.Name = value; } OnPropertyChanged(nameof(Name)); OnPropertyChanged(nameof(Error)); } } //(中略 同じように各プロパティの宣言) public override string Error { get { if (_errors.Count > 0) return "不正な値が入力されています"; if (!string.IsNullOrWhiteSpace(_model.Address) && _model.PostCode == 0) { return "住所に準じた郵便番号が入力されていません"; } return null; } } } }
neelabo👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

①ですがInitializeComponentは自動生成されるメソッドで、DebuggerNonUserCodeAttribute属性が適用されています。

DebuggerNonUserCodeAttribute属性というのは、デフォルト設定時は外部コードとして扱われて、デバッガで停止やステップイン実行できません。
このため、次にデバッガで停止できる場所がMainViewModel クラスの Itemsプロパティだったのでしょう。

[ツール][オプション][デバッグ]にある「マイコードのみを有効にする」のチェックを外すと、デバッガでの停止やステップイン実行ができるようになります。

②ですが、インスタンスが生成された後、各変数の初期化処理が実行されます。
今回の場合ですが、Itemプロパティの宣言や_keywordの宣言部分ではなく
= new ObservableCollection<CustomerViewModel>();や = "";の初期値を代入する部分が実行されるためにデバッガで停止することとなっています。

③コンストラクタは各変数の初期化が終了した後に実行されます。

投稿2017/08/13 23:34

YAmaGNZ

総合スコア10258

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

oftolisan

2017/08/14 01:21

YAmaGNZ様 細やかなお気遣い本当に助かります、ありがとうございます。 ご回答中の「②ですが、インスタンスが生成された後、」の部分についてですが、 このインスタンスは MainViewModel クラス のインスタンスということになりますでしょうか? その場合、MainViewModel を new している処理があるのでは、と思ったのですが ソリューション全体を MainViewModel  で検索してもみつけられませんでした。 重ねて恐縮ですが、この点についてアドバイスいただけませんでしょうか。 検索でヒットした MainViewModel  は、以下の2箇所です。 1) 同クラスの宣言部   public partial class MainViewModel : CustomerViewModel 2) MainWindow.xaml.cs の public partial class MainWindow : Window クラス内の下記メソッド private void MainWindow_DataContextChanged( object sender, DependencyPropertyChangedEventArgs e) { MainViewModel x = DataContext as MainViewModel;     (以下、略)
YAmaGNZ

2017/08/14 11:42

MainViewModelクラス内の変数の初期化となれば、MainViewModelクラスのインスタンスが生成されたタイミングになります。 ソース全体が分からないので何とも言えませんが、データバインディング等でxaml側でインスタンスが生成されているとか考えられないでしょうか?
oftolisan

2017/08/14 12:22

ありがとうございます!! 自分なりに考えてみたのですが、下記のようなイメージでしょうか? 1) App.xaml に StartupUri="MainWindow.xaml" があることで、まず、MainWindowが立ち上がり  Mainメソッドである(?)、MainWindow(){**} コンストラクタが実行される。 2) MainWindow.xamlには、下記があるので、続いて、(new演算子は無くても) MainViewModel  クラスのインスタンスが作成される  <Window.DataContext> <l:MainViewModel/> </Window.DataContext> 3) インスタンスが生成された場合の既定の動きとして、自分で{}内の処理を記述した  コンストラクタが存在する場合は(今回 → MainViewModel() { Clear(); } )、  先に、同クラス内の各変数(フィールド)の初期化処理が実行され、  次にコンストラクタが実行される。 重ねて恐縮ですが、よろしくお願いいたします。
YAmaGNZ

2017/08/14 13:02

そうですね <Window.DataContext> <l:MainViewModel/> </Window.DataContext> これでMainViewModelクラスは生成されます。 実行される順序としては、今回はそのような感じで問題ないと思います。 クラスが生成された時の詳しい実行順序はmituhaさんが書いていらっしゃるように検索していただければよいかと思います。
oftolisan

2017/08/14 13:05

お忙しい所ご対応頂き誠にありがとうございます。大変ためになりました。 あきらめずに勉強をつづけたいと思います。
guest

0

少しだけ。

①なぜ、MainWindow(){} の InitializeComponent(); からMainViewModel クラスの Itemsプロパティに処理が飛んだ(?)のか、

MainWindowのInitializeComponentの処理は、bin\Debug\MainWindow.g.cs 等に自動生成されており、

/// <summary> /// InitializeComponent /// </summary> [System.Diagnostics.DebuggerNonUserCodeAttribute()] [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")] public void InitializeComponent() { if (_contentLoaded) { return; } _contentLoaded = true; System.Uri resourceLocater = new System.Uri("/CameraController;component/mainwindow.xaml", System.UriKind.Relative); #line 1 "..\..\MainWindow.xaml" System.Windows.Application.LoadComponent(this, resourceLocater); #line default #line hidden }

のようになっています。
DebuggerNonUserCodeAttribute属性がついているため、デバッガーで追いかけた場合は飛ばされています。
オプションで設定を変えられたとも思いますが、今のところは内部的な処理なので飛ばされているとした方が良いと思います。

②その後、なぜ、同クラス内のフィールド変数 _keyword の宣言に飛んだのか
③その後、なぜ、同クラス内の MainViewModel() のコンストラクタに飛んだのか

C# コンストラクタ 初期化順序 等で検索をすればわかると思います。

投稿2017/08/13 23:19

mituha

総合スコア385

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

oftolisan

2017/08/14 01:05

mituha様、ご回答まことにありがとうございます。 検索キーワードまでご教示いただき、大変助かります。 本当にありがとうございます。精進します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問