Alamofire5のRequestInterceptorを試す

背景

  • Alamofireを使ってAPI通信していると、アクセストークンのリフレッシュを共通化したくなる
  • そこで使えるのがRequestInterceptor
  • RequestAdapter, RequestRetrierについての日本語記事はあったがRequestInterceptorの日本語記事は見当たらなかったため情報提供する

説明

  • RequestInterceptorにはAdaptとRetryという2つのプロトコルが存在する
  • Adaptは毎回実行される処理(たとえばアクセストークンのセットなど)、RetryはAPIをリトライ実行するための条件(たとえば401のときのみアクセストークンを更新してリトライするなど)およびリトライ前に実行したい処理を記述する

コード

import Foundation
import Alamofire
import SwiftyJSON

final class AppRequestInterceptor: Alamofire.RequestInterceptor {

    private var accessToken: String = ""
    
    init () {}

    func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
        // accessToken取得処理(省略)

        var urlRequest = urlRequest

        urlRequest.setValue("Bearer " + self.accessToken, forHTTPHeaderField: "Authorization")

        completion(.success(urlRequest))
    }

    func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
        guard let response = request.task?.response as? HTTPURLResponse, response.statusCode == 401 else {
            return completion(.doNotRetryWithError(error))
        }

        // 401になったらここにくる
        // アクセストークン更新処理(仮)
        AF.request("/refresh/token",
            method: .get,
            parameters: parameters,
            encoding: URLEncoding(destination: .queryString)
        ).responseJSON {response in
            switch response.result {
                case .success(let value):
                    let json = JSON(value)
                    guard let accessToken = json["access_token"].string else {
                        return
                    }
                    self.accessToken = accessToken
                    completion(.retry)
                case .failure(let error):
                    completion(.doNotRetryWithError(error))
            }
        }
    }
}

参考

Alamofire/AdvancedUsage.md at master · Alamofire/Alamofire · GitHub

Authentication with signed requests in Alamofire 5 - SwiftLee

パスポートの最速受け取り方法について調べた

背景

  • 仕事で海外に行く予定が入ったが、パスポートの有効期限が先月で切れていた
  • 日本出発日は2週間後
  • とある事情で渡航期間はずらせず可能な限りパスポートを取得する必要がある

前提

  • 筆者は東京都住みで勤務先も東京
  • 期限切れが判明したのは土曜日

先に結論

  • 都内のパスポートセンターから通常通り申請する

短く受け取ることができる方法

早期発給・緊急発給

  • 早期発給は自治体によって対応している
    • 調べたところ広島県が対応しているが首都圏の自治体は対応していなかった
  • 緊急発給は人道的なケースでないと申請不可
    • 人道的ケースとは、海外における親族等の病気、事故、天災等による死亡、危篤、入院等により、関係者が緊急に渡航しなければならない場合

日曜に申請する

  • 調べたところ埼玉県が日曜申請を行っている!
    • 日曜だからといって交付手続きは平日と同じで、交付予定を見る限り月曜に申請するより早く取得することが可能
  • これがわかったときは「これだ!」と思った。しかしよくよく調べてみると、パスポートは住民登録をしている都道府県で申請する必要があるということ
  • 居所での申請も可能だが条件があり、縁もゆかりもない土地では申請できない

まとめ

  • ということで普通に月曜申請いってきます

参考

ソフトウェアファーストを読んだ

背景

  • どのようなキャリアを描くべきか悩んでいたところ、たまたまtwitterのTLで見かけた本の内容に興味を惹かれ読んでみた
  • キャリアに関する章は5章で、1~4章は伝統企業に勤めるおじさん向けの内容だったのでさっと読み流した

www.amazon.co.jp

5章内容

ソフトウェアファーストなキャリアを築くには

  • T型・π型人材を目指そう
    • スキル構築には2つのベクトルがある
      • 自身の専門性(縦軸)
      • 専門外の領域などの周辺知識(横軸)
    • この縦軸と横軸を伸ばすことをT型のスキル構築という
    • 専門性を1本から複数にすることでπ型人材になる
  • 縦軸を増やすために
    • 自分のキャリアを第三者視点でみてもらうの大事(著者は1年に1度親しいヘッドハンターと会い情報交換していた)
    • 戦略的に自ら選択する必然性が重要な一方でコネクティングザドッツのような偶然性も影響する
    • 次の学習対象を選定する際は、自分の現在持っている専門領域を島と捉え、今いる島から遠い・ベクトルの離れた島を選ぶとよい
    • 興味を持てるような島を選んだほうが学習の影響に好パフォーマンスを与える
  • 数年に1度キャリアを棚卸ししてみるとよい f:id:shibu_t:20200919171039p:plain
  • エンジニアのキャリアは大きく3種類に分別できる
    • エンジニアを極める
    • エンジニアリングマネージャ
    • プロダクトマネージャ

及川さんのキャリアヒストリー

  1. DECに新卒入社。配属は希望と違う営業サポート部門だったがコミュニケーションとプレゼンスキルを向上させることができた
  2. 米国マイクロソフトに出向。CSを勉強したことがなかったため高いハードルを掲げ必死に勉強した。
  3. マイクロソフトに転職し会社の業績も好調な一方で、自分のキャリアがマイクロソフトに依存しすぎていることに気づき恐怖を覚える
  4. googleに入社。入社するためにはかなり努力をし、googleの全プロダクトを調べSWOT分析し自分ならこんなプロダクトをつくると仮説を立てて面接にのぞんだ
  5. Incrementsに入社。自分でレーダーチャート状のスキルチャートをつくり自分の社会における影響力を分析した。そうすることで自分の強み・弱みを把握でき、自分の強みが発揮できる「日本企業であるベンチャー企業」に転職した

感想

  • 下記が大事だなと感じた
    • 定期的に自分の現在地点を知ること
    • 好奇心(危機感)を常にもつこと
    • 高い目標を掲げること

文字列にインデックスを貼る場合カラム長に気をつけろ

何が起きた?

下記のようなcreate tableをプルリクに混ぜたところ、先輩に文字列にインデックス貼るときはカラム長制限あるから気をつけろとコメントいただきました。

CREATE TABLE `test` (
  `hoge` varchar(255) NOT NULL,
  PRIMARY KEY (`hoge`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

確かに調べてみると制限があるらしい。

プリフィクスのサポートやプリフィクスの長さ (サポートされている場合) は、ストレージエンジンに依存します。たとえば、InnoDB テーブルではプリフィクスの長さを最大 767 バイトに、また innodb_large_prefix オプションが有効になっている場合は 3072 バイトにすることができます。MyISAM テーブルの場合、プリフィクスの制限は 1000 バイトです。

https://dev.mysql.com/doc/refman/5.6/ja/create-index.html

でもcreate table文通ったのなんでだろうとmysqlの設定をみていると、innodb_large_prefix オプションが有効になっていた。 そのためwarningが出ずにテーブル作成できてしまった模様

mysql> SHOW VARIABLES LIKE '%large_prefix%';
+---------------------+-------+
| Variable_name       | Value |
+---------------------+-------+
| innodb_large_prefix | ON    |
+---------------------+-------+
1 row in set (0.01 sec)

対応したこと

絵文字が入る予定ないのでutfmb4をやめてutf8にしました

参考

next4us-ti.hatenablog.com

エンジニアリング組織論への招待を読んでみた

背景

  • 新卒のメンターをしていることもあり、下記記事を見て本を読んでみたくなった

blog.shibayu36.org

  • この本は一度読んだだけでは全体像が見えにくい
  • そこで一度整理するために内容をざっくりまとめてみる

1章 思考のリファクタリング

1-1 すべてのバグは思考の中にある

  • 思考のリファクタリングとは頭の中で発生してしまう無駄なプロセスを削除して、問題解決に向かって明確に行動ができるように促すもの
  • 言い換えるならば「不確実性に向き合う」考え方

1-2 不確実性とエンジニアリング

  • エンジニアリングとは「何か役に立つものを実現していく学問」
  • 実現には「はじめ」と「おわり」がある
  • ソフトウェアにおける実現:曖昧な要求からスタートし、具体的で明確ななにかに変わっていく
  • つまり「曖昧さ」を減らし「具体性・明確さ」を増やす行為がエンジニアリング
  • 組織において、上位レイヤー(社長など)の指示は曖昧で、下位レイヤー(現場)の行動ほど具体的になる
  • 抽象的で自由度のある指示でも動ける組織の方が不確実性を削減しやすくスケールしやすい(マイクロマネジメントはその逆)
  • 不確実性の高さ:発生する確率が偏っているほど不確実性の量は減っていく(たとえば降水確率50%より80%の方が不確実性が低い)
  • 不確実性は「情報」によって減少させることができる(たとえば降水確率50%だと思っている人に80%という情報伝えることにより減らすことができる)
  • 人間にとって不確実性は「未来」と「他人」から発生する
  • 人間は不確実性に向き合うことを避ける習性があるため、エンジニアリングによって不確実性を減らしていくことが必要

1-3 情報を生み出す考え方

  • 3つの考え方を用いて思考をリファクタリングする
    • 論理的思考の盲点→人は論理的でなくなる可能性があるためどういうときにそれが起こるのか知った上で問題解決にのぞむ方法
    • 経験主義と仮説思考→経験主義:情報を入手するために行動を起こす考え方 / 仮説思考:限定された情報であっても全体像を想定し確かめる方法
    • システム思考:全体の関係性を捉える考え方

1-4 論理的思考の盲点

  • 論理的思考とは演繹的思考のことで前提であるルールと事象から結論を導くこと。たとえば、
    • ルール:人間は皆死ぬ
    • 事象:私は人間である
    • 結論:私は死ぬ
  • といったように導く考え方
  • 論理的思考には2つの重要な前提がある
    • ルールと事象を正しく認知できること
    • 正しく演繹できること
  • 一方で、人間は感情が入り込むと事実を正しく認知できなくなる
  • 論理的思考能力とは「感情的になる瞬間を知りその影響を少なくできる」能力でもある
  • どういうときに事実を認知できないのか知ることで、論理的思考を制限されないようにする

ベーコンの4つのイドラ

  • 種族のイドラ:人間が本来もっている性質から生じる錯覚や偏見。たとえば、「遠くにあるものが小さく見える」であるとか、「暗い場所ではものがはっきりと見えない」といったこと。
  • 洞窟のイドラ:個々を取り巻く環境から、外の世界を知らずに一般的なことだと決めつけて理解することから生じる偏見。たとえば、「自分がそうだから、他の人もそうだと思う」「自分の家では目玉焼きにマヨネーズだからみんなそうだ」といったこと
  • 市場のイドラ:言葉の不適切な使用から生じる誤解や偏見のこと。たとえば、「噂話やデマを信じてしまう」ということ
  • 劇場のイドラ:伝統や権威を無批判に受け入れて、誤った考えであっても信じてしまうことから生じる偏見。たとえば、「偉い人の言っていることは正しいだろうと思う」といったこと

認知の歪み

  • ゼロイチ思考:白か黒か、敵か味方かのように2分法で物事を捉え、間のグラデーションを認識できずに捉えてしまうという認知の歪み
  • 一般化のしすぎ:ある事例が1つや2つあると、その根拠に全体をそうだと決めつけてしまう
  • すべき思考:他人に対し、彼らは道徳的に「すべきである」「しなければならない」と期待し、それを強制するような思考パターン
    • すべき思考は自分にも向く。「社会人は就職しなければならない」等
  • 選択的注目:見たいものしか見なくなること。たとえば、最近景気が悪いというニュースを見たときに、街を見渡すと、景気が悪そうな事象ばかりが目についてしまう。逆に、景気が良いと言われると、街に溢れている景気が良さそうな事象ばかりが目につく
  • 結論の飛躍:LINEで既読スルーするのは怒っている証拠だなど。
  • 感情の理由付け:感情のみを根拠に自分の考えが正しいとしてしまうこと。たとえば「不安」な気持ちからこのプロジェクトは失敗すると結論づけることなど。

認知的不協和

  • 自分の感情や行動の矛盾を解決するために認知自体を歪めること。たとえばタバコは体に悪いと知りながら喫煙している人が何らかの理由をつけて喫煙を正当化すること

怒り(扁桃体)をコントロールする

  • 人間は怒るときに感情に飲み込まれやすい 。怒りとは何か?
  • 恐怖や危機を察知すると深く考えるよりも先に「吠えたり」「戦闘の準備をする」ようにできている
  • 自分や仲間が脅かされると恐怖や危機を司る扁桃体が発火し怒りの感情が発生する
  • 自分自身のアイデンティの範囲が広いひと(仲間思いや家族思いの人)は怒りを感じる射程が広いので怒りやすい傾向がある
  • 一方で狭い人は攻撃だと思わないから恐怖を覚えない(なかなか怒らない人は優しいと同時に何にも関心がない人かも)

怒りを悲しみとして伝える

  • 自分が怒りを感じたときに、相手に怒りを悲しみとして伝えることは重要な方法の一つ
  • 「それは自分にとって大事なことで、その発言は大事なものをぞんざいに扱われたようで悲しい」のように

1-5 経験主義と仮説思考

経験主義

  • コントロールできるもの / できないものを見極め、できるものがあれば行動を起こせば情報を取得することが可能
    • 例えば新人が仕事ができないのであれば「新人の能力や内心」はコントロールできないのに対し、「新人への指示の出し方や行動へのフィードバック」はコントロールできる
  • コントロールできないはずのものを自分の行動で変化させようと試みる場合は、観察できる必要がある(なぜなら観察できないと行動しても変化したかわかりようがないため)
  • 「コントロールできるもの」を操作し、そして、「観測できること」を通じて、その結果を知識にすること

仮説思考

  • データは銀の弾丸ではない
  • データから仮説を推論しそれが正しいのか検証するというのが重要

1-6 システム思考

  • 一番わかりやすいたとえは生態系。益虫や害虫といった個別の最適化が生態系全体に影響を与え、思いもよらないような変化をもたらしてしまうという現象
  • システム思考とは「個別最適化」が全体最適にならない問題を分析し、より本質的な問題解決を支援するフレームワークのこと

1-7 人間の不完全性を受け入れる

  • 複数人で何かを実現していく工程では1人の人間では怒らないはずの不確実性が発生する
  • コミュニケーションの不確実性は情報の偏りを生み出す。このことを経済学では「情報の非対称性」という(片方の人は知っていてもう片方の人は知らない情報があること)
  • また、自分と他人の利害が異なる場合に、それぞれがそれぞれにとって合理的な行動をとったとしても、全体として不合理な行動をとってしまうことを「限定合理性」という

1章まとめ

  • 「エンジニアリング」は、不確実性を下げ、情報を生み出す過程のこと
  • 自分自身がどのように本能に囚われるのかを知り、仮説と検証を通じて、未来の不確実性を下げていきながら、同じ目的で働いているはずの人々との間にあるコミュニケーションの不確実性も減らしていく必要がある

2章 メンタリングの技術

2-1 メンタリングで相手の思考をリファクタリング

「自ら考える人材を作る」ためのテクニック

  • 「依存型」と「自立型」の2種類あるが、上司のここまで自立してほしいという期待値と部下のここまでやるべきという期待値はズレるもの
  • 自分自身のコンフォートゾーンはなかなか変えることができない
  • 一方で自分から考えて動いた結果、評価されたとか、周囲からの尊敬を集めた場合は「自律的に動くことは楽しい」という感情が生まれる
  • メンタリングとは、そのような自己効力感がコンフォートゾーンを上回るように導く手段である

効果的なメンター / メンティーの関係性

  • 効果的な関係性になる条件は3つある(HRT)
    • 謙虚(Humility):お互いに弱さを見せられる
    • 敬意(Respect):お互いに敬意をもっている
    • 信頼(Trust):お互いにメンティ(自身)の成長期待をもっている
  • メンターは課題を指摘する人ではなく、課題に一緒に向き合い成長を支援するというコミットが求められる
  • 個人の成長を階段にたとえて、「成長の階段を上る」と表現することがあるが、階段を上るには次のことをする必要がある
    • 階段を認識させる
      • 「階段があるよ」ではなく「足元は大丈夫?」と問うほうがよほど効果的。メンタリングでは、見えていない課題に自分から気づかせることを重視する
    • 壁に梯子をかける
      • 大きめの課題に対しては一歩一歩梯子をかけてあげて階段を登っている実感を提供するのが重要
    • 階段を上りたくさせる
      • そもそも階段を上ることが「おもしろくない」ことであれば、誰も階段を登らない

「他者説得」から「自己説得」に

  • 人から与えられた説得による知識を「他者説得」、自分自身で気がついたことを「自己説得」という
  • メンタリングでは、他者説得よりも自己説得を重視しその獲得を促す
  • 自己説得を生み出すには答えをいうのではなく、適切な質問の積み重ねが重要
    • (例)後輩「今やっているプロジェクトは、残業時間が多すぎてダメなんです。プロダクトオーナーはそれを問題と思ってないんです」
    • 先輩「プロダクトオーナーは、それを問題と思っていないって、どうして判断したの?
    • 後輩「残業が多い状況をそのままにしているからです」
    • 先輩「なぜ、そのプロダクトオーナーは残業してまで、今やっていることをしたいと思っているの?」
    • 後輩「考えたことなかったです」
    • 先輩「その人が何を考えているかわからなければどうしたらいい?」
    • 後輩「話し合えてなかったですね。そういうことか。何で気がつかなかったんだ」
    • いきなり「プロダクトオーナーと話し合いなよ」では次の行動にコミットできない可能性が高い

「悩む」と「考える」の違い

  • メンタリングを進めていくにあたって、メンターはメンティが「悩んでいる」のか「考えている」のかを判断することが重要
  • 悩んでいる状態は頭の中に様々なことが去来し生産的ではない状態
  • 考えている状態はメモ帳などに課題を書き出し分解したり抽象化したりし次に進むために何かと忙しく行動をとっている状態
  • メンタリングとは「次にとるべき行動」がはっきりするように促す必要がある。それが曖昧なままでは「悩み」は継続してしまう

2-2 傾聴・可視化・リフレーミング

  • メンターは、メンティに対して、「問題を解決してあげよう」という意識ではなく、「モヤモヤしていない問題に変換してあげよう」と考えることが重要
  • 解決できない問題の場合解けない理由を1つずつなくしていきひとりでも解決できる問題に変換していく
    • 感情的に固執していて解けないので、「傾聴」をする
    • 客観視できずに解けないので「可視化」をする
    • そもそも解けない問題なので前提を変える「リフレーミング」をする

傾聴

  • まずは頭の中にいっぱいになった不安や迷いの水を吐き出させてあげることが重要。「水でいっぱいになったコップには水は注げない」
  • 傾聴とただ話をきくことは違う。傾聴は「相手」を中心としながら、「相手の思考が整理され、前向きに考えられるように支援」するように意識して、会話を行う
    • 「相手の」感情への共感を言動で表す
      • 共感という言葉の意味は、「相手がそのような気持ちになった理由を理解する」
      • それに対して、「自分が相手と同じ気持ちになる」ことを同感という
      • 傾聴において示すべきことは、「共感」であって、「同感」ではない
    • 「相手の」話の内容を「可視化」をする
    • 「相手の」思考の「盲点」を探索しながら質問をする

問題の「可視化」と「明晰化」

  • 次は、メンティの視線を、メンターではなく、「問題」へと向ける必要がある
  • メンティの抱えている問題の形をメンティもメンターも見ることができるものとして、ホワイトボードやノートなどに書き出してみるとよい
  • 物理的に視線を変えて、「問題と私たち」という構図にする。それによって、メンティは自分が抱えている問題を、客観的な問題として捉えることができるようになる。これを問題の「可視化」という
  • また、可視化をしていく工程で、「感情的に固執してしまっている要素」を引き剥がして、問題が何であるかをはっきりとさせていく必要がある。この工程を問題の「明晰化」という
  • 可視化と明晰化をする上でのテクニック
    • 事実と意見をわける
    • フォーカスポイントをつくる(「解きたい問題は何か」「その答えの範囲はどこからどこまでか」ということのフォーカス(焦点)をはっきりさせていくことが重要)
    • 衝突から比較可能への変換(選択肢・比較軸・評価方法を明確にする)

認知フレームとリフレーミング

  • 私達は「不安」や「焦り」「優先順位」等によって物事を認知する枠組みは変わる
  • 対話によって認知フレームを変えることをリフレーミングという
  • 発言の中から認知フレームを発見することができる(本書の表参照)
  • 認知フレームを示唆するキーワードが見つからない場合においても前提を問うような質問(たとえば「~が問題なのは、そもそも何ででしたっけ?」とか「~がないと具体的に何が困るんでしたっけ?」)をすることで明らかにすることもできる
  • また、この中で「一番重要だと思うものは何ですか?」というように前提の優先順位を問うこともリフレーミングを促す

2-3 心理的安全性の作り方

  • メンティが遅刻した場合、「なんで、(あなたは)遅れたの?」よりも「連絡がなかったから、(私は)心配したよ」と伝えれば、責めるようなニュアンスは減り、存在を承認しているという明確なアクノレッジメントに変化させることができる

2-4 内心でなく行動に注目する

  • 「心構え」や「力不足」といったメンター自身が本来、コントロールできないところに注目して、指導をする方法は避けなければならない

ドラム式洗濯機がほしい

背景

現在は縦型洗濯機を利用しているが、下記理由で不便が生じてきた

  • 海の近くに住んでいるため風が強く外に干すのが大変
  • 部屋干しだと乾くのに時間がかかる&場所取る
  • 子供ができ洗濯回数が増えたため、上記の課題がより鮮明になってきた

ドラム式洗濯機について色々調べてみる

ドラム式洗濯機について

kakakumag.com ドラム式洗濯機についてよくわかっていなかったので調べてみたが上記記事がよくまとまっていた。

要約するとこんな感じ

  • 洗濯機には縦型とドラム式がある
  • 縦型はドラム式に比べて
    • 本体&電気代安い
    • 洗浄力高い
    • 乾燥機能がついていないもしくはついていても乾燥力低い
    • フィルターの掃除が楽(ドラム式の場合掃除の頻度が増えるみたい。ググったところ週1〜2でやらないとつまってしまうとのこと)
  • ドラム式洗濯乾燥機選びのポイント
    • 価格
    • 洗濯容量&乾燥容量(乾燥容量は洗濯容量の半分な洗濯機が多い)
    • 洗剤/柔軟剤自動投入機能の有無
    • スマホ連携機能の有無
    • 電気代
    • 騒音
    • 糸くずフィルター/乾燥フィルターの手入れのしやすさ

個人的には着目したいポイント

  • 本体代と電気代
    • 知人いわくドラム式はこわれやすいとのことなので、本体代/電気代は抑えめにしておきたい
  • 洗剤/柔軟剤自動投入機能
    • なくてもいいけど便利らしいので
  • フィルターのメンテしやすさ

上記観点から選ぶと下記が候補になってくる

20万切ってて電気代も安く洗剤/柔軟剤自動投入機能ついてるのはこれだけだった

kakaku.com

kakaku.com

kakaku.com

しっかし価格コムのリスト表示めちゃ便利だな。これに項目追加できればなおよしだけど

価格.com - 日立(HITACHI)のドラム式洗濯機 価格の安い順

C#の参照型の値渡しに気をつけろ

背景

  • C++のコードをC#にしたら想定外の挙動になった

C++のコード

#include <iostream>
#include <vector>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
using p = pair<int, int>;

void foo(vector<int> A)
{
    if (A.size() == 10)
    {
        return;
    }

    A.push_back(1);
    foo(A);

    // print
    rep(i, A.size())
    {
        cout << A[i];
    }
    cout << endl;
}

int main()
{
    foo(vector<int>(1, 1));
}

出力結果

1111111111
111111111
11111111
1111111
111111
11111
1111
111
11

C#のコード

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        Program obj = new Program();
        obj.Foo(new List<int> { 1 });
    }

    void Foo(List<int> A)
    {
        if (A.Count == 10)
        {
            return;
        }

        A.Add(1);
        this.Foo(A);

        // print
        foreach (var e in A)
        {
            Console.Write(e);
        }
        Console.WriteLine();
    }
}

出力結果

1111111111
1111111111
1111111111
1111111111
1111111111
1111111111
1111111111
1111111111
1111111111

!?

Aの値が更新されてしまっている

改善する

  • どうやらListは参照型らしい
  • refをつけなければ値渡しになる
  • つまり参照型の値渡しなのでオブジェクトを渡すときと同じ挙動になる
  • したがって、渡された値まるごと置き換えた場合は値がコピーされるが(値渡し)、中身の一部を変えた場合(配列に要素追加するなど)は呼び出し元も変更されてしまう(共通のレジスタを参照)
  • ということで渡された値まるごと置き換えて値渡しにしてあげればよい
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        Program obj = new Program();
        obj.Foo(new List<int> { 1 });
    }

    void Foo(List<int> A)
    {
        var B = new List<int>(A);
        if (B.Count == 10)
        {
            return;
        }

        B.Add(1);
        this.Foo(B);

        // print
        foreach (var e in A)
        {
            Console.Write(e);
        }
        Console.WriteLine();
    }
}

出力結果

1111111111
111111111
11111111
1111111
111111
11111
1111
111
11

まとめ

C#

  • Listは参照型
  • 引数に渡すときはrefを付けない限り値渡しで渡される
  • 参照型の値渡しはオブジェクトを渡すときと同じ挙動になる

C++

  • vectorは値型
  • &を付けない限り値渡しで渡される