20191001のC#に関する記事は7件です。

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


alibaba_function.PNG
(最近画面のUIが変わったので公式ドキュメントと実際の画面が異なっている場合があります。)



  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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 が対になってるかをチェックする
とある処理をブロック的に分けたいときに有用そう
ブラケット {} で囲むと ブロックとして扱われてスコープが影響する

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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許容性の指定は総称型の利便性にも大きく貢献します。理解を深めてより利便性を享受したいと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

多重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#ではどういう作りにするのが定石なんだろうか。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C#: WEBフォーム画面でSQLにデータをINSERTする

SAMPLE

下記のWEBフォームを作成し、名前と誕生日を入力してボタンを押下するとSQLserver上のテーブルにデータをINSERTする。
image.png

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

image.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

C#で簡単にSNMP getする方法

.netのクラスライブラリになかったのね

 極々簡単な(GETしかしない)SNMPマネージャの作成を検討してて、最初はWMIのSNMP機能で出来るやろ?と思っていたんですが、WMIは対Windowsしか接続出来ないようにみえました…(出来るのかわからなかった)
 他の手段をさがしていくつか見つけたのでメモしておきます。

UDP使ってでGet部分だけでも実装する

C#でASN.1のObject Identifierのエンコードを行う

この方のこの一連のシリーズの投稿を参考にGet出来るまで自力コーディングする方法。

nugetからLextm.SharpSnmpLibをDLして使う

Lextm.SharpSnmpLib

nuget探すといくつか出てくるんですが、これはMITライセンスで使えます。簡単なサンプルはgithubにあるのでそれ見るとすぐ出来ました。

OLEPRNLib

 COMコンポーネントを使う方法。

最初に見かけたのがWindows標準機能だけでsnmpgetする(PowerShell)
でpowershellだったのですが、COMコンポーネントなら使えるのでは?というのがきっかけ。

参照設定でoleprn 1.0 Type Libraryを追加します

コメント 2019-10-01 102413.png

以下のように使います。

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");

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unityを用いたAndroidアプリの開発で詰まったところ

はじめまして、最近個人開発で収益を得ようと奔走しているushijiroです。初投稿なのでお手柔らかにお願いします(*´ω`*)

先日Chick Jumpというアプリをリリースしました。内容はUnityを用いて開発したシンプルなミニゲームで、以前デベロッパー登録して放置していたGoogleアカウントがあったので、AndroidアプリとしてPlayStoreからリリースしました。

ミニゲームということもあり、ゲーム自体は3日間で完成したのですが、それ以外の部分は初めての連続でなかなか苦戦しました。そこでこの記事では、詰まったところをまとめておこうと思います。

あと、もしよかったら遊んでみてください。未だにダウンロード数が0なので…(ヽ´ω`) こちらからダウンロードできます。
20190927185444.png

環境

  • 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を使って公開しました。アプリをリリースして間もないので、正直問題ないか定かではありませんが、審査はパスし、今の所削除もされていません。

最後に

勉強目的かつ短期間で作ったミニゲームとはいえ、全くダウンロードされず、アプリ開発の厳しさをまざまざと思い知らされる結果となりました。評価云々以前に存在しら認識されないというのはなかなか応えますね…(´・ω・`) やはり最初から宣伝込みで独創的なアプリを作るべきと感じました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む