115

匿名型を返すクエリがあり、クエリはメソッドにあります。これをどのように書きますか:

public "TheAnonymousType" TheMethod(SomeParameter)
{
  using (MyDC TheDC = new MyDC())
  {
     var TheQueryFromDB = (....
                           select new { SomeVariable = ....,
                                        AnotherVariable = ....}
                           ).ToList();

      return "TheAnonymousType";
    }
}
4

16 に答える 16

105

できません。

object、、またはオブジェクトのコンテナ、たとえばIEnumerable<object>IList<object>などのみを返すことができます。

于 2012-04-09T12:42:34.367 に答える
49

戻ることができdynamicます。これにより、匿名タイプのランタイムチェックバージョンが提供されますが、.NET4以降のみです。

于 2012-04-09T12:44:35.630 に答える
29

匿名タイプを返すことはできません。返品可能なモデルを作成できますか?それ以外の場合は、を使用する必要がありますobject

これは、ジョン・スキートがこのテーマについて書いた記事です。

記事のコード:

using System;

static class GrottyHacks
{
    internal static T Cast<T>(object target, T example)
    {
        return (T) target;
    }
}

class CheesecakeFactory
{
    static object CreateCheesecake()
    {
        return new { Fruit="Strawberry", Topping="Chocolate" };
    }

    static void Main()
    {
        object weaklyTyped = CreateCheesecake();
        var stronglyTyped = GrottyHacks.Cast(weaklyTyped,
            new { Fruit="", Topping="" });

        Console.WriteLine("Cheesecake: {0} ({1})",
            stronglyTyped.Fruit, stronglyTyped.Topping);            
    }
}

または、ここに別の同様の記事があります

または、他の人がコメントしているように、あなたは使用することができますdynamic

于 2012-04-09T12:42:40.640 に答える
18

返す必要がある場合は、匿名型の代わりに Tuple クラスを使用できます。

注: Tuple には最大 8 つのパラメーターを指定できます。

return Tuple.Create(variable1, variable2);

または、元の投稿の例:

public List<Tuple<SomeType, AnotherType>> TheMethod(SomeParameter)
{
  using (MyDC TheDC = new MyDC())
  {
     var TheQueryFromDB = (....
                           select Tuple.Create(..., ...)
                           ).ToList();

      return TheQueryFromDB.ToList();
    }
}

http://msdn.microsoft.com/en-us/library/system.tuple(v=vs.110).aspx

于 2014-07-02T16:55:55.260 に答える
12

C# コンパイラは 2 フェーズ コンパイラです。最初のフェーズでは、名前空間、クラス階層、メソッド シグネチャなどをチェックするだけです。メソッド本体は、2 番目のフェーズでのみコンパイルされます。

メソッド本体がコンパイルされるまで、匿名型は決定されません。

したがって、コンパイラには、最初のフェーズでメソッドの戻り値の型を決定する方法がありません。

これが、匿名型を戻り値の型として使用できない理由です。

.net 4.0以降を使用している場合、他の人が示唆しているように、Dynamic.

私があなただったら、おそらく型を作成し、メソッドからその型を返すでしょう。そうすれば、将来のプログラマーがコードを維持しやすくなり、読みやすくなります。

于 2012-04-09T13:22:58.000 に答える
9

3つのオプション:

オプション1:

public class TheRepresentativeType {
    public ... SomeVariable {get;set;}
    public ... AnotherVariable {get;set;}
}

public IEnumerable<TheRepresentativeType> TheMethod(SomeParameter)
{
   using (MyDC TheDC = new MyDC())
   {
     var TheQueryFromDB = (....
                           select new TheRepresentativeType{ SomeVariable = ....,
                                        AnotherVariable = ....}
                           ).ToList();

     return TheQueryFromDB;
   } 
}

オプション2:

public IEnumerable TheMethod(SomeParameter)
{
   using (MyDC TheDC = new MyDC())
   {
     var TheQueryFromDB = (....
                           select new TheRepresentativeType{ SomeVariable = ....,
                                        AnotherVariable = ....}
                           ).ToList();
     return TheQueryFromDB;
   } 
}

オブジェクトとして繰り返すことができます

オプション3:

public IEnumerable<dynamic> TheMethod(SomeParameter)
{
   using (MyDC TheDC = new MyDC())
   {
     var TheQueryFromDB = (....
                           select new TheRepresentativeType{ SomeVariable = ....,
                                        AnotherVariable = ....}
                           ).ToList();

     return TheQueryFromDB; //You may need to call .Cast<dynamic>(), but I'm not sure
   } 
}

動的オブジェクトとして繰り返し処理し、それらのプロパティに直接アクセスできるようになります

于 2012-04-09T12:47:13.557 に答える
2

この場合、オブジェクトのリストを返すことができます。

public List<object> TheMethod(SomeParameter)
{
  using (MyDC TheDC = new MyDC())
  {
     var TheQueryFromDB = (....
                           select new { SomeVariable = ....,
                                        AnotherVariable = ....}
                           ).ToList();

      return TheQueryFromDB ;
    }
}
于 2012-04-09T12:43:13.850 に答える
2
public List<SomeClass> TheMethod(SomeParameter)
{
  using (MyDC TheDC = new MyDC())
  {
     var TheQueryFromDB = (....
                           select new SomeClass{ SomeVariable = ....,
                                        AnotherVariable = ....}
                           ).ToList();

      return TheQueryFromDB.ToList();
    }
}

public class SomeClass{
   public string SomeVariable{get;set}
   public string AnotherVariable{get;set;}
}

独自のクラスを作成し、それに対してクエリを実行することが、私が知っている最善の解決策です。私が知っている限り、匿名型の戻り値を別のメソッドで使用することはできません。方法。IQueryable以前はorとして返していましたIEnumerableが、匿名型変数の内部を確認することはできません。

以前、いくつかのコードをリファクタリングしようとしていたときに、このようなことに遭遇しました。ここで確認できます:リファクタリングと個別のメソッドの作成

于 2012-04-09T12:49:54.900 に答える
1

dynamic キーワードのみを使用できます。

   dynamic obj = GetAnonymousType();

   Console.WriteLine(obj.Name);
   Console.WriteLine(obj.LastName);
   Console.WriteLine(obj.Age); 


   public static dynamic GetAnonymousType()
   {
       return new { Name = "John", LastName = "Smith", Age=42};
   }

ただし、動的なタイプのキーワードを使用すると、コンパイル時の安全性、IDE IntelliSense などが失われます...

于 2018-04-01T11:44:08.640 に答える
1

実際には、特定のユースケースでメソッドから匿名型を返すことができます。みてみましょう!

C# 7 では、わずかな制約はありますが、メソッドから匿名型を返すことができます。ローカル関数と呼ばれる新しい言語機能を、間接的なトリックと一緒に使用します (間接的な別のレイヤーでプログラミングの課題を解決できますよね?)。

これは私が最近特定したユースケースです。からロードした後、すべての構成値をログに記録したいと考えていますAppSettings。なんで?デフォルト値に戻る欠落した値に関するいくつかのロジック、いくつかの解析などがあるためです。ロジックを適用した後に値をログに記録する簡単な方法は、それらをすべてクラスに入れ、ログファイルにシリアル化することです (log4net を使用)。また、設定を処理するための複雑なロジックをカプセル化し、それらを処理する必要があるものから分離したいと考えています。一度だけ使用するために存在する名前付きクラスを作成する必要はありません。

匿名型を作成するローカル関数を使用してこれを解決する方法を見てみましょう。

public static HttpClient CreateHttpClient()
{
    // I deal with configuration values in this slightly convoluted way.
    // The benefit is encapsulation of logic and we do not need to
    // create a class, as we can use an anonymous class.
    // The result resembles an expression statement that
    // returns a value (similar to expressions in F#)
    var config = Invoke(() =>
    {
        // slightly complex logic with default value
        // in case of missing configuration value
        // (this is what I want to encapsulate)
        int? acquireTokenTimeoutSeconds = null;
        if (int.TryParse(ConfigurationManager.AppSettings["AcquireTokenTimeoutSeconds"], out int i))
        {
            acquireTokenTimeoutSeconds = i;
        }

        // more complex logic surrounding configuration values ...

        // construct the aggregate configuration class as an anonymous type!
        var c = new
        {
            AcquireTokenTimeoutSeconds =
                acquireTokenTimeoutSeconds ?? DefaultAcquireTokenTimeoutSeconds,
            // ... more properties
        };

        // log the whole object for monitoring purposes
        // (this is also a reason I want encapsulation)
        Log.InfoFormat("Config={0}", c);
        return c;
    });

    // use this configuration in any way necessary...
    // the rest of the method concerns only the factory,
    // i.e. creating the HttpClient with whatever configuration
    // in my case this:
    return new HttpClient(...);

    // local function that enables the above expression
    T Invoke<T>(Func<T> func) => func.Invoke();
}

匿名クラスの構築に成功し、複雑な設定管理を処理するロジックをすべてCreateHttpClient独自の「式」内にカプセル化しました。これは、OP が望んでいたものとはまったく異なる場合がありますが、現在の C# で現在可能な匿名型を使用した軽量なアプローチです。

于 2019-10-25T14:37:05.967 に答える
-1

このコンストラクトの名前がわかりません。これは匿名型と呼ばれていると思いましたが、間違っている可能性があります。とにかく私はこれを探していました:

private (bool start, bool end) InInterval(int lower, int upper)
{
    return (5 < lower && lower < 10, 5 < upper && upper < 10);
}

private string Test()
{
    var response = InInterval(2, 6);
    if (!response.start && !response.end)
        return "The interval did not start nor end inside the target";
    else if (!response.start)
        return "The interval did not start inside the target";
    else if (!response.end)
        return "The interval did not end inside the target";
    else
        return "The interval is inside the target";
}

これを呼び出す別のスタイルは次のとおりです。

    var (start, end) = InInterval(2, 6);
于 2021-08-30T20:02:04.840 に答える