- 投稿日:2019-10-01T23:51:17+09:00
FunctionComputeでC#が使える話 (1)
きっかけ
Alibaba CloudのFunction Computeについて調べていたところ、使用出来る言語にC#が含まれていたので調べてみました。
Function Compute
公式ドキュメントには、以下の説明がありました。
他社クラウドと同様にイベント駆動型のサーバーレスなサービスです。Alibaba Cloud Function Compute は、イベント駆動型のフルマネージドコンピューティングサービスです。Function Compute を使用すると、管理や O&M を考慮することなく、あらゆる種類のアプリケーションやサービスをすばやく構築できます。マルチメディアデータを処理する一連のバックエンドサービスを数日で完了できます。
他社サービスとの使用言語比較
2019/10/01現在、他社のイベント駆動型のサーバーレスなサービスと使用言語について比較しました。
比較したサービス
- AWS Lambda
- Azure Functions
- GCP Cloud Functions
- Alibaba Function Compute
AWS Azure GCP Alibaba Java 〇 〇 × 〇 PHP × × × 〇 Node.js 〇 〇 〇 〇 C# 〇 〇 × 〇 Ruby 〇 × × × Python 〇 〇 〇 〇 Go 〇 × 〇 × PowerShell 〇 〇 × × F# × 〇 × × TypeScript × 〇 × ×
Function Computeで使えるC#について
Function Computeは.NET Core2.1ランタイムをサポートしています。
現在の.NET Coreは2.1がLTSとなっていて、2系は2.2まで出ています。
2019年9月下旬に.NET Core 3.0がリリースされました。おそらく今後3.x系に移行すると思いますが、3.x系がLTSにならないとFunction Computeのランタイムもアップデートされない可能性があると予想されます。
そのため、ローカル環境での開発はバージョンに注意する必要があります。
.NET Coreの2.x系と3.x系では色々と変更が入っているので、予め3.x系にアップデートしても修正箇所が少なくて済むようなコード設計にしておくと楽だと思います。
Function ComputeでC#の関数を作成する
OSSにファイルをアップロードまたは、zipファイルをアップロードする必要があります。
Java以外のランタイムとは関数の設定画面が異なるので、手順が整理出来次第記事を追加していきます。
記事追加しました!(2019/10/03)
https://qiita.com/cube8080/items/ce27de96138b1aecad6b
(最近画面のUIが変わったので公式ドキュメントと実際の画面が異なっている場合があります。)
Function Compute C# SDK
https://github.com/aliyun/fc-csharp-sdkFunction Compute C# Libraries
https://github.com/aliyun/fc-dotnet-libs
- 投稿日:2019-10-01T20:42:27+09:00
Study C# - Scope, CompileSymbol -
プログラミング C# をまとめてメモしてみる
普段はPHPだとかJavascriptばっかり触っているので、とても新鮮で楽しいでございます!動作環境
VisualStudio for Mac - COMMUNITY -
バージョン8.3.1(build 18)
スコープ
基本的には他の言語とも変わりない
Block内で有効なスコープは
- Block前に宣言されたもの
- Blockの中で宣言されたもの
int a1 = 0; { // このスコープで作成されたものは外には出れない int a2 = 0; // ① a1 = 1; } // Blockの中にある変数を宣言しようとすると、Block内がコンパイルエラー(①)になる↑ int a2 = 9; // ②①(Block内) と ②(Block外) の2箇所で宣言すると以下のような現象が発生する
②のいちで二重定義になっているが、①でエラーが発生する。短いコードならまだすぐに発見できるけどもスコープが広くなると厄介になりそうな予感宣言空間 なるものによる仕様らしい
コンパイルシンボル
プリプロセスで参照されるディレクティブ
#define
#if
#else
#elif
#endif
#define DEBUG // ステートメントでは無いので最後のセミコロンはいらない using System; // 最初のステートメント ... ... ... #if DEBUG Console.WriteLine("Debug Mode."); #else Console.WriteLine("Prod Mode."); #endif
#define
はファイルの一番先頭に記述 ※ 最初のステートメントよりも先に定義する必要がある
ステートメントよりも前であればいいので、コンパイルシンボルをコンパイルシンボルで分けて定義するとかわけのわからないこともできる(ということ)#define AAA #if AAA #define BBB #else #define CCC #endif #define DDD using System; ...
System.Diagnostics.Conditional
を利用することで、コンパイルシンボルの設定に合わせてMethodの定義が可能
コンパイルシンボルが定義されていればコンパイルされ、定義されていなければコンパイルのタイミングでよしなに削除してくれる。
デバッグ用のメソッドとかこれでかける(Prodビルドのときは製品に含まれない)CompileMethod(); [System.Diagnostics.Conditional("DEBUG")] static void CompileMethod() { Console.WriteLine("DEBUG Compile Method"); }#error #warning
コンパイルシンボルのなかで強制的にエラー/ワーニングを発生させるときにつかう
#error えらーなんよ #warning わーにんぐ
#line
あまり使いみちも無い気もするけども
エラーが起こったときに強制的に行番号とファイル名を書き換える#line 999 "FUGAFUGA" int a = "string"; // int型にStringを入れようとしている エラーエラーコンソールの表示では
行番号:999
ファイル名:FUGAFUGA
となる
たとえこの場所がmain.csの10行目であろうとも#region #endregion
なにもしない。$region と #endregion が対になってるかをチェックする
とある処理をブロック的に分けたいときに有用そう
ブラケット{}
で囲むと ブロックとして扱われてスコープが影響する
- 投稿日:2019-10-01T20:04:25+09:00
C#8.0世代の総称型制約 ジェネリクスとnull許容性の関係
C#8.0時代の総称型制約
はじめに
C#8.0でnull許容性が追加されたことで、総称型制約にも機能が追加されました。
動作を検証している中で、既存のキーワードの動作の認識が間違っていた箇所があったので、復習の意味も含めて記事を書いてみます。キーワード
C#8.0で新しいキーワード
notnull
が追加されました。null不許容の参照型または値型を示すことができます。また、従来
class
制約だったものが、class
,class?
の両制約に役割が分かれることになります。ここで「おや?」と思ったのが、この記事を書いたキッカケです。何かというと「
struct?
という制約ってあったっけ?」という疑問でした。結論から言えばこの制約はありません。null許容性の話においては、参照型と値型では全く違うということをきちんと認識しておくことが必要です。
参照型 参照型? unmanaged型 値型 値型? 未指定 〇 〇 〇 〇 〇 notnull
〇 - 〇 〇 - class
〇 - - - - class?
〇 〇 - - - struct
- - 〇 〇 - unmanaged
- - 〇 - - new()
☆ ☆ 〇 〇 〇 notnull,new()
☆ - 〇 〇 - class ,new()
☆ - - - - class?,new()
☆ ☆ - - - 総称型でnull許容性を指定する方法
値型の場合
値型で、かつnull許容も不許容も受け入れる場合を考えてみます。
この場合、
struct
制約を利用して、型引数をnull不許容に指定した上で、null許容したい箇所だけ?
(Nullable<T>
)を指定すれば良いのです。null許容値型とnull不許容値型は違う型として認識されるので、必要な場合はオーバーロードを書くことができます。
値型制約// nullを許容しない void Do<T>(T item) where T : struct { } // 引数でnullを許容する void Do<T>(T? item) where T : struct { }参照型の場合
参照型の場合はというと、型引数で
class?
制約を利用する方法と、型引数ではclass
制約を使用したうえでnull許容したい箇所だけ?
を指定する方法の二通りが考えられます。また、参照型ではnull許容性が違っても同じ型として認識されますので、オーバーロードとして書き分けることはできません。
参照型制約// 型引数も引数もnull不許容参照型 void Do0<T>(T item) where T : class { } // 型引数はnull不許容参照型で、引数はnull許容参照型 void Do1<T>(T? item) where T : class { } // 型引数がnull許容参照型ならば、引数もnull許容参照型 // 型引数がnull不許容参照型ならば、引数もnull不許容参照型 void Do2<T>(T item) where T : class? { } // これは書けない // void Do3<T>(T? item) // where T : class? { }補足:
notnull
制約
notnull
制約の時、T?
型を指定することはできません。これは値型と参照型でnull許容性の扱いが全く異なるからです。notnull制約void Do<T>(T item) where T : notnull { } // これは書けない //void Do<T>(T? item) // where T : notnull { }特殊な制約
使用頻度は高くないですが、特殊な制約についても調べてみます。
デリゲート型制約
デリゲート型制約もnull許容性を指定できるようになっています。null許容性に応じて、
Delegate
,Delegate?
を指定できます。挙動も直感的で、例えばAction?
を受け入れるか受け入れないかが変わります。
Delegate
Delegate?
Action
Action?
Delegate
〇 - 〇 - Delegate?
〇 〇 〇 〇 列挙型制約
列挙型制約もnull許容性を指定できるようになっています。null許容性に応じて、
Enum
,Enum?
を指定できます。ただし、Enum?
については、あまり直感的な挙動ではないことを覚えておきましょう。
MyEnum
という列挙型を定義したとして、Enum?
型制約のついた型引数にMyEnum?
を指定することはできません。これはstruct
制約と同じ理屈です。総合的に考えると、
Enum
制約はstruct
制約と組み合わせて使ったほうが扱いやすいように思います。参考public abstract class Enum : ValueType {} // 独自定義したとする enum MyEnum { ... }
Enum
Enum?
MyEnum
MyEnum?
Enum
〇 - 〇 - Enum?
〇 〇 〇 - struct Enum
- - 〇 - その他の仕様変更
C#8.0から
unmanaged
制約の挙動が変わっています。これは入れ子のunmanaged型もunmanaged型と扱われるように改善されたためです。例えば
unmanaged
制約した型引数に対して、C#8.0からは(int,int)
を扱うことができるようになっています。まとめ
C# 8.0 の目玉機能であるnull許容性の指定は総称型の利便性にも大きく貢献します。理解を深めてより利便性を享受したいと思います。
- 投稿日:2019-10-01T19:51:42+09:00
多重Dictionaryをつくりたかった
C#は素人なので定石がわかりません。
こういう連想配列があったとしましょう。
PHP$datetimes = [ 'past' => [ 'yesterday' => new DateTime('yesterday'), 'lastweek' => new DateTime('last week'), ], 'future' => [ 'tomorrow' => new DateTime('tomorrow'), 'nextyear' => new DateTime('next year'), ] ];いや、こんな意味のわからない配列なんて作らねえよという抗議は全くもってその通りなのですがそこはスルーします。
実際はAPIに飛んできたリクエストをユーザ単位にまとめるみたいな処理をするところで、何個飛んでくるかわからないという仕様です。PHPで書くとこんな感じでさくっとできます。
PHP$datetimes = []; foreach($request as $v){ $datetimes[$v['tense']][$v['key']] = new DateTime($v['value']); }一瞬で書けてとってもらくちん。
ということで、この連想配列をC#に移植しようとしたのですが、どうもこのような構造について話をしているところがほとんど見当たりませんでした。
多重連想配列はC#では禁忌なのだろうか。連想配列はDictionaryを使えばいいみたいですが、これは基本的に値がひとつです。
NameValueCollectionというのが目的に近かったのですが、これは値がstring
固定みたいです。なぜ。
Microsoft.Experimental.Collectionsは名前が既に危ない。試しに
Dictionary
の中にDictionary
を突っ込んでみたら普通にいけました。var datetimes = new Dictionary<string, Dictionary<string, DateTime>>(); var list1 = new Dictionary<string, DateTime>(); list1.Add("yesterday", new DateTime("yesterday")); list1.Add("lastweek", new DateTime("last week")); var list2 = new Dictionary<string, DateTime>(); list2.Add("tomorrow", new DateTime("tomorrow")); list2.Add("nextyear", new DateTime("next year")); datetimes.Add("past", list1); datetimes.Add("future", list2);ただ、この構造だと
list1
などの中間変数が必要になってしまいます。
一気にdatetimes["past"].Add("yesterday", new DateTime("yesterday"));
みたいなことはできないの?var datetimes = new Dictionary<string, Dictionary<string, DateTime>>(); // The given key "past" was not present in the dictionary datetimes["past"].Add("yesterday", new DateTime("yesterday")); // Object reference not set to an instance of an object datetimes.Add("past", null); // An item with the same key has already been added datetimes.Add("past", new Dictionary<string, DateTime>{{"yesterday", new DateTime("yesterday")}} ); datetimes.Add("past", new Dictionary<string, DateTime>{{"lastweek", new DateTime("last week")}} ); // これはOK datetimes.Add("past", new Dictionary<string, DateTime>{{"yesterday", new DateTime("yesterday")}} ); datetimes["past"].Add("lastweek", new DateTime("last week"));Add自体はできるみたいですが、親Dictionaryのキーの有無によって動作を変えなければなりません。
キーが存在しない場合のみキーをAddし、その後はその中身だけAddしないといけないようです。
なんというかとても面倒。もっとなんかマシな方法ってのがあるんだろうけどよくわかりませんでした。
そもそもC#ではどういう作りにするのが定石なんだろうか。
- 投稿日:2019-10-01T13:07:42+09:00
C#: WEBフォーム画面でSQLにデータをINSERTする
SAMPLE
下記のWEBフォームを作成し、名前と誕生日を入力してボタンを押下するとSQLserver上のテーブルにデータをINSERTする。
SQLserver
CREATE TABLE [test_data] ( id INT IDENTITY(1,1) , name NVARCHAR(200) , birth DATE , PRIMARY KEY (id))ASP.NET
<div> 名前を入力してください <asp:TextBox ID="TextBoxName" runat="server"></asp:TextBox> <br /> <br /> 誕生日を入力してください <asp:TextBox ID="TextBoxBirth" runat="server"></asp:TextBox> <br /> <br /> <asp:Button ID="ButtonInsert" runat="server" OnClick="ButtonInsert_Click" Text="Insert" /> </div>C#
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Data; using System.Data.SqlClient; namespace WebApplication1 { public partial class WebForm1 : System.Web.UI.Page { protected void ButtonInsert_Click(object sender, EventArgs e) { var query = String.Format("INSERT INTO [test_data] ( name, birth ) VALUES ( '{0}','{1}' )", TextBoxName.Text, TextBoxBirth.Text ); using (SqlConnection con = new SqlConnection("Data Source=ServerName; Initial Catalog=DatabaseName; uid=UserName; pwd=Password")) { try { // データベースの接続 con.Open(); using (var transaction = con.BeginTransaction()) using (var command = new SqlCommand() { Connection = con, Transaction = transaction }) { try { // コマンドのセット command.CommandText = query; // コマンドの実行 command.ExecuteNonQuery(); // コミット transaction.Commit(); } catch { // ロールバック transaction.Rollback(); throw; } } } catch (Exception exception) { Console.WriteLine(exception.Message); throw; } finally { // データベースの接続終了 con.Close(); } } } } }EXAMPLE
- 投稿日:2019-10-01T10:50:16+09:00
C#で簡単にSNMP getする方法
.netのクラスライブラリになかったのね
極々簡単な(GETしかしない)SNMPマネージャの作成を検討してて、最初はWMIのSNMP機能で出来るやろ?と思っていたんですが、WMIは対Windowsしか接続出来ないようにみえました…(出来るのかわからなかった)
他の手段をさがしていくつか見つけたのでメモしておきます。UDP使ってでGet部分だけでも実装する
C#でASN.1のObject Identifierのエンコードを行う
この方のこの一連のシリーズの投稿を参考にGet出来るまで自力コーディングする方法。
nugetからLextm.SharpSnmpLibをDLして使う
nuget探すといくつか出てくるんですが、これはMITライセンスで使えます。簡単なサンプルはgithubにあるのでそれ見るとすぐ出来ました。
OLEPRNLib
COMコンポーネントを使う方法。
最初に見かけたのがWindows標準機能だけでsnmpgetする(PowerShell)
でpowershellだったのですが、COMコンポーネントなら使えるのでは?というのがきっかけ。参照設定でoleprn 1.0 Type Libraryを追加します
以下のように使います。
var snmp = new OLEPRNLib.SNMP(); snmp.Open("127.0.0.1", "public", 3, 10000); var result = snmp.GetAsByte("1.3.6.1.2.1.1.5");
- 投稿日:2019-10-01T10:20:19+09:00
Unityを用いたAndroidアプリの開発で詰まったところ
はじめまして、最近個人開発で収益を得ようと奔走しているushijiroです。初投稿なのでお手柔らかにお願いします(*´ω`*)
先日Chick Jumpというアプリをリリースしました。内容はUnityを用いて開発したシンプルなミニゲームで、以前デベロッパー登録して放置していたGoogleアカウントがあったので、AndroidアプリとしてPlayStoreからリリースしました。
ミニゲームということもあり、ゲーム自体は3日間で完成したのですが、それ以外の部分は初めての連続でなかなか苦戦しました。そこでこの記事では、詰まったところをまとめておこうと思います。
あと、もしよかったら遊んでみてください。未だにダウンロード数が0なので…(ヽ´ω`) こちらからダウンロードできます。
環境
- OS: Windows 10
- Unity: Unity 2019.2.6f1
- AdMob: GoogleMobileAds-v4.0.0
- GPGS: GooglePlayGamesPlugin-0.9.64
JDKやAndroid Studioを自分でインストールする必要はない
インストールする際にAndroid Build Support、Android SDK & NDK Toods、Open JDKにチェックを入れておくと、特に何もしなくてもAndroidアプリをビルドできるようになります。すでにUnityをインストールしている場合、Unity Hubからモジュールを追加できます。
Play Services ResolverがGradle failed to fetch dependencies.で止まる
恐らくJAVA_HOMEという環境変数が設定されていません。ビルドインのJDKは
C:\Program Files\Unity\Hub\Editor\Unityのバージョン\Editor\Data\PlaybackEngines\AndroidPlayer\Tools\OpenJDK\Windows
にあるので、システム環境変数にJAVA_HOMEという名前でパスを通しておきましょう。ビルド時にNeither AdManager nor AdMob is enabled yet.というエラーが出る
GoogleMobileAdsSettingsのAdMob App IDが設定されていない可能性があります。GoogleMobileAdsSettingsは、Assets > Google Mobile Ads > Settings...から開くことができます。
実装に問題はなさそうなのにGPGSが動かない
プレイストア経由でないと動作しないようです。テストする際は内部テスト版としてリリースしましょう。
アプリの署名で求められるSHA1フィンガープリントをどうやって調べるのかわからない
内部テスト版でも良いのでストアにアプリをアップロードすると、SHA1が入力された状態になるので楽ちんです。
どうしても自分で調べたい場合、コマンドライン上から先程のビルドインJDKのディレクトリに移動し、以下のようなコマンドを入力するとSHA1を確認できます。
bin\keytool.exe -v -list -keystore キーストアの場所アプリを64ビット要件に準拠していないと言われる
Project SettingsのConfigurationからScripting BackendをIL2CPPに変更し、Target ArchitecturesのARM64にチェックを入れることで64ビットに対応したアプリをビルドできます。
APKが最適化されていないと言われる
Build Settings画面のBuild App Bundle(Google Play)にチェックを入れておくと、アプリをAndroid App Bundleとしてビルドできます。生成された.aabという拡張子のファイルをアップロードしましょう。同時に生成されるzipファイルの方はよくわかりません(;´∀`)
version codeをすでに使っていると言われる
Project SettingsのOther Settingsの中にあるBundle Version Codeを変えましょう。更新するたびに一つずつ加算していけば良いと思われます。
You device dose not match the hardware requirements of this application
実機で動かした際このような警告が出て、構わずContinueするとクラッシュしたり画面がピンクになる場合、Project SettingsのOther SettingsにあるAuto Grapics APIにチェックを入れると直るかもしれません。
どうやらここにチェックが入っていると下にあるGraphics APIの中から選ばれるようで、デフォルトではVulkan等ごっつい面々が揃い踏みしており、最新の端末でしか動きそうにありません。
プライバシーポリシーをどう書けばいいかわからない
App Privacy Policy Generatorという素敵なサービスがあります。私はこのツールで生成したプライバシーポリシーをGitHub Pagesを使って公開しました。アプリをリリースして間もないので、正直問題ないか定かではありませんが、審査はパスし、今の所削除もされていません。
最後に
勉強目的かつ短期間で作ったミニゲームとはいえ、全くダウンロードされず、アプリ開発の厳しさをまざまざと思い知らされる結果となりました。評価云々以前に存在しら認識されないというのはなかなか応えますね…(´・ω・`) やはり最初から宣伝込みで独創的なアプリを作るべきと感じました。