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

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

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

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

Q&A

解決済

3回答

37287閲覧

C#「値を返さないコード パスがあります。」のエラー

Lark7

総合スコア7

C#

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

1グッド

0クリップ

投稿2016/05/11 12:33

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

C#にて、対象文字列とワイルドカードを引数として渡したら
対象文字列がワイルドカードの条件に当てはまるかどうかをTrue or Falseを返すようなメソッドを
作りたいと考えています。

なお、ワイルドカードは「ABC*,DEF??,*GH」といったように複数の条件をカンマ区切りで
一度に指定できるようにしたいです。

例えば、ObjText="TestText"である場合
Wildcard="ABC,Te*"ならTrueを返し、Wildcard="Te*,ABC,"でもTrueを返すが
Wildcard="ABC,DE*"ならFalseを返すといった形です。

###発生している問題・エラーメッセージ

CS0161 'Form1.test(string, string)': 値を返さないコード パスがあります。

下記のように記述したところ、上記のようなエラーが出てコンパイルできない状況です。

###該当のソースコード

public bool test(string ObjText, string Wildcard) { string[] stArrayData = Wildcard.Split(','); foreach (string stData in stArrayData) { //ワイルドカードの文字列を正規表現の文字列に変換する var regexPattern = Regex.Replace(stData, ".", m => { string s = m.Value; if (s.Equals("?")) { //?は任意の1文字を示す正規表現(.)に変換 return "."; } else if (s.Equals("*")) { //*は0文字以上の任意の文字列を示す正規表現(.*)に変換 return ".*"; } else { //上記以外はエスケープする return Regex.Escape(s); } } ); bool rg = new Regex(regexPattern).IsMatch(ObjText); if (rg) { return true; } else { return false; } } }

###試したこと
例外が起きた場合に if(rg)の中のreturn分を通らない場合があるのかもしれないと考え、
Try-Catchをいろいろな場所に記述してCatch内にreturnを入れてみたりしたのですが、エラーに変化はありませんでした。ワイルドカードを正規表現に変換するところの処理は正直あまり理解できておらず、見当違いなことをしているかもしれず恐縮なのですが、お知恵をお貸しいただければ幸いです。

###補足情報(言語/FW/ツール等のバージョンなど)
C#を使ったワイルドカードの使用については、下記を参考にしました。
http://qiita.com/kazuhirox/items/5e314d5e7732041a3fe7

iwamoto_takaaki👍を押しています

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

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

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

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

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

guest

回答3

0

public int Test(int[] xs){ foreach(var x in xs){ return 1; } }

これは一見、すべてのパスで値を返しそうですが、
xsが空の場合はforeach内に入らないのでパス無しになります。

投稿2016/05/11 13:02

ozwk

総合スコア13521

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

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

Lark7

2016/05/11 13:11

なるほど。。 当方のコードの問題はforeach内に入らないという抜け道があったのですね。 どんな場合でも一度はforeach内に入る前提でいろいろとトライしてしまっていました。 takasima20さんのご回答と合わせて、foreach外にreturn falseを記述する意味を改めて納得いたしました。 ありがとうございました。
guest

0

ベストアンサー

エラーとは関係ないですが、Wildcardの最初のやつしか判定しないスね。
自分だったら、ループ内では true のみ return し
ループの外(全部ハズレだった場合) false を return する
って形にするかなあ。

投稿2016/05/11 12:49

takasima20

総合スコア7458

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

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

Lark7

2016/05/11 13:00

おっしゃる通りですね。。。 ご指摘通り修正したらうまくいきました。 煮詰まっていたので大変助かりました!ありがとうございました。
guest

0

メソッドの分割に慣れていないようですね。
ワイルドカードを正規表現クラスに返還するメソッドを加えてみました。

c#

1public bool test(string text, string wildcards){ 2 foreach(string wildcard in wildcards.Split(',')){ 3 var reg = ConvertWildcardToReges(wildcard); 4 if(reg.IsMatch(ObjText)){ 5 return True; 6 } else { 7 return False; 8 } 9 } 10} 11 12private Regrex ConvertWildcardToReges(string wildcard){ 13 //ワイルドカードの文字列を正規表現の文字列に変換する 14 var regexPattern = Regex.Replace(wildcard, ".", 15 m => { 16 string s = m.Value; 17 if (s.Equals("?")) { 18 //?は任意の1文字を示す正規表現(.)に変換 19 return "."; 20 } else if (s.Equals("*")) { 21 //*は0文字以上の任意の文字列を示す正規表現(.*)に変換 22 return ".*"; 23 } else { 24 //上記以外はエスケープする 25 return Regex.Escape(s); 26 } 27 }); 28 29 retrun new Regex(regexPattern).IsMatch(ObjText); 30}

ちなみにこのコードはエラーが残ったままです。(バグを新しく作りこんでしまったかもしれません。)

testメソッドがずいぶんスッキリしていることに同意してもらえるはずです。
このコードを見て、エラーの原因に気づいてもらえたらよいのですが・・・

さらにヒントを続けます。

C#

1var ret = test("TestTest", "");

このretの値はTrueでしょうかFalseでしょうか。
おそらく、変更前のコードではわかりづらかったかもしれませんが、このコードで考えるとすぐわかると思います。

短いメソッドのほうがエラーは見つけやすいので、上手にメソッドの分割をしたほうが良いと思います。

投稿2016/05/11 13:15

iwamoto_takaaki

総合スコア2883

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

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

Lark7

2016/05/11 13:42

コメントありがとうございます。 >メソッドの分割に慣れていないようですね。 おっしゃる通り、我流でVBAを触ってきて、C#はここ最近始めたばかりでして、なんとかコンパイル通るようにするのが精いっぱいという状況でお恥ずかしい限りです。 (メソッドの分割流儀などはVBAでもC#でもそれほど違いがある話もないと思うので言い訳にもなりませんが。。。) 前にコメントいただいたozwkさんのご指摘からすると wildcardsがnullの場合のパスなしで、ご提案いただいたコードでもtestメソッドはコンパイル通らないかなぁと考えました。 下記はまさにwildcardsがnullの例、ということですかね? var ret = test("TestTest", "");
iwamoto_takaaki

2016/05/11 14:51

nullではないです。 長さ0の文字です。Nullと0の差は説明しずらいですが、test("TestTest", null)は呼び出し側でエラーになります。 wildcardをSplitしたときに長さ0の配列が返ってくるので、foreachの中の処理は実行されず。値が帰らないまま処理が抜けます。 foreach構文のあとにreturn False;を入れるというのが答えになります。 ループや条件式が複雑になるとこの手モレが発生しやすくなります。一目でわかる大きさにメソッドを分割するように心がけてください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問