シチュエーションとしては、
string型をstring型ではない別の型として定義することで実装ミスに事前に気づけるようにしたいです。
例えば、string型でif文の判定をする場合、
C#
1string item = "book"; 2int price; 3 4if (item == "book") { 5 price = 100; 6} else { ... }
のように書くかと思いますが、
string型だと他のどんなstring型でも比較できてしまうことで不具合につながるので、悩みどころです。
C#
1string userName = "John"; 2int price; 3if (userName = "book") { // UserNameはそもそもここで比較されるべきではない 4 price = 100 5} else { ... }
これを、string型をラップ?するようなMyString型があれば、
C#
1MyItemString item = "book"; 2string userName = "John"; 3int price; 4 5if (item == (MyItemString)"book") { 6 price = 100; 7} else if (userName == (MyItemString)"book") { // 型が違うためコンパイルエラーになる 8 price = 200; 9} else { ... }
のようにコンパイルエラーとしてビルド時に間違いに気づくことができるかと思います。
【質問】
- ユーザー定義のstring型を作成することはできますか?
また、できる場合はその方法をお教え頂けるとありがたいです。 - 上記のようなstringの比較の実装ミスによる不具合を防ぐ別の方法はありますか?
できれば、ユーザー定義型のstringとして扱いたいですが、より良い方法があればご教授いただきたいです。
以上、皆さんのお知恵をお貸しいただければ嬉しいです。
あまりメリットのあるこのをやろうとしてるようには見えないのですが(大事なのは変数が保持している情報そのものだと思うので)、実装も例ではなく具体的な要件のほうが良いかと思います。
>stringの比較の実装ミス
ここが他者にはイメージ伝わりにくいのではと。
enum を使うか、if の代わりに switch 式を使えば良いと思います。
インターンプールというのがあるのをご存じですか? 文字列を key に、ヒープ上の String オブジェクトのアドレスを value に持つハッシュテーブルのようなものです。コードに "John" と書くとコンパイルされる時にそれはインターンプールに置かれます。なので、質問者さんが書いたようなコード (MyItemString)"book" のようなことをするのは不可能かと思います。
@m.ts10806
> あまりメリットのあるこのをやろうとしてるようには見えないのですが
具体的にどのような理由でメリットがないと感じられましたか?
コンパイル時点で実装ミスに気づけるという意味で十分メリットがあると考えています。
> 大事なのは変数が保持している情報そのものだと思うので
こちらに関しては自分も同意です。ただ、「型」にも情報が含まれており、変数+型含めての情報ですよね?
変数に入っている情報のみでプログラムが構成できるのであれば、クラスを始めとするユーザー定義型は必要ないはずですし
@Zuishin
質問の書き方が悪かったためか、意図が伝わっておらず申し訳ございません。
enum/if/switch式による実装がどうこうという意味ではなく、string型をそのまま使うことで他のあらゆるstringと比較されうるということに危険性があり、それを解消したいということです。
@SurferOnWww
インターンプールというのは知りませんでした。
stringの場合に使用される保存領域ということですかね。
> コードに "John" と書くとコンパイルされる時にそれはインターンプールに置かれます。なので、質問者さんが書いたようなコード (MyItemString)"book" のようなことをするのは不可能
stringがインターンプールに置かれるので、不可能ということですが、理由と結論の間にギャップがあり理解できませんでした。
(MyItemString)"book"のようにキャストすることが無理ということでしょうか?
それとも、そもそもstringから派生させたようなユーザー定義のstring型を作成することが無理ということでしょうか?
> インターンプールというのは知りませんでした。
String Intern などをキーワードにググって調べるなどして勉強してください。
> (MyItemString)"book"のようにキャストすることが無理ということでしょうか?
何故そういうことができると思うのか分かりません。ご自分でやってみて、もし出来たら、どのようにしたのか逆に教えてもらえませんか?
TypeScript の共用体型のようなものをお望みでしょうか?
https://js.studio-kingdom.com/typescript/handbook/advanced_types#union_types
それなら、将来のバージョンで入る計画はありますが、今のところはできません。
enum を使用するのが最も近いと思います。
> (MyItemString)"book"のようにキャストすることが無理ということでしょうか?
演算子のオーバーロードを使えばできなくはありませんが、それで問題が解決するかは疑問です。
> 演算子のオーバーロードを使えばできなくはありませんが
そうですね、前言「何故そういうことができると思うのか分かりません」は取り消します。失礼しました。
> string型だと他のどんなstring型でも比較できてしまうことで不具合につながる
この話の意味がわからないです…
あるデータAの内部表現(っていうか)が文字列であってそれをstringとして実装し,
Aとは別の意味合いのデータBの内部表現もまた文字列であってstringとして実装したとき,
AとBは全く異なる概念であるから「AとBを比較する」というのは「話の上では異常事態」なのだけどもコード的に(型的に)は問題ないのがなんか嫌だ
…的な話なのでしょうか?
(もしもそういう話なら,AもBもstring丸出しで実装しなければ良いというだけなのでは…? 内部表現がstringたることがmustだとして,それを抱えている型を適当に用意するのではダメなのか?)