-2

私は次の声明を持っています:

var itemsFromList = from item in ListItems 
                    where item.Countries != null 
                    select item;

したがって、国に存在するすべての値を返すことができます (一部は空です)。同じリストに、インスタンス都市の他の列があり、次のように変更する必要があります。

var itemsFromList = from item in ListItems 
                    where item.cities != null 
                    select item;

次のような変数を使用して、同じステートメントを使用して、空でない都市または国を返す方法はありますか?

var itemsFromList = from item in ListItems 
                    where item.variable != null 
                    select item;
4

3 に答える 3

2

あなたの質問は非常に不明確ですが、let句を使用すると、サブ式の結果を分割できます。おそらくこれ(?):

var itemsFromList = from item in ListItems 
                    let Variable = item.Countries
                    where Variable != null 
                    select item;

これが実際に何を達成するかはわかりません。

Variable私の他の唯一の考えは、コンパイル時に何が何であるかがわからず、何かを注入したいということですか?

@DarenThomasが言うように、Variableが実際にLinqステートメントの外部にある場合、Variable反復ごとに変更される可能性がないため、ステートメント全体が機能しなくなります。

于 2012-06-13T13:35:57.403 に答える
2

変数は、後日定義される変数であることが意図されているように見えます。式をそのように変更可能にしたい場合は、リフレクションを使用するのが最善の策です。

まず、目的のプロパティの PropertyInfo への参照を取得する必要があります。これを行うには、Type.GetProperty(string name)を呼び出します。PropertyInfo への参照を取得したら、PropertyInfo.GetValue(Object obj, Object[] index)を呼び出して、特定のインスタンスの値を取得できます。

指定したプロパティが null でない項目のみを取得する LINQ クエリを作成する例を次に示します。

// Declare this as a Generic method of Type T so that we can pass in a
// List containing anything and easily get the appropriate Type object
public static IEnumerable<T> SelectNonNull<T>(
    IEnumerable<T> ListItems, string propertyName)
{
    IEnumerable<T> itemsFromList;
    // Get a reference to the PropertyInfo for the property
    // we're doing a null-check on.
    PropertyInfo variable = typeof(T).GetProperty(propertyName);
    if (variable == null)
    {
        // The property does not exist on this item type:
        // just return all items
        itemsFromList = from item in ListItems
                        select item;
    }
    else
    {
        itemsFromList = from item in ListItems
                        // GetValue will check the value of item's
                        // instance of the specified property.
                        where variable.GetValue(item, null) != null
                        select item;
    }
    return itemsFromList;
}

質問の結果を取得するには、次のようにこの関数を使用できます。

var NonNullCountries = SelectNonNull(ListItems, "Countries");
var NonNullCities = SelectNonNull(ListItems, "cities");

別の方法として、これを拡張メソッドとして宣言することもできます (他の Linq メソッドと同様)。

public static IEnumerable<T> SelectNonNull<T>(
    this IEnumerable<T> source,
    string propertyName)
{
    PropertyInfo variable = typeof(T).GetProperty(propertyName);
    if (variable == null)
    {
        // Specified property does not exist on this item type:
        //just return all items
        return from item in source
                select item;
    }
    else
    {
        return from item in source
                where variable.GetValue(item, null) != null
                select item;
    }
}

次に、複数の呼び出しを連鎖させることができます。たとえば、「都市」と「国」が null であるすべてのエントリを除外したい場合は、次のように使用できます。

var NonNullCitiesOrCountries = ListItems.SelectNonNull("Countries")
                                        .SelectNonNull("cities");

注: SelectNonNull は IEnuerable を返すだけです。クエリの結果を取得するには、それを列挙する必要があります。

于 2012-06-13T14:03:23.047 に答える
0

私があなたの質問を正しく理解していれば、ハードコードされたフィールドCountryを動的なものに置き換えたいと思うでしょう。

その場合、関数 from toとして宣言する必要がありますVariable(代わりに呼び出しましょう) 。getNotNullFieldListItemobject

Func<ListItem, object> getNotNullField;
if (...) {
    getNotNullField = item => item.Countries;
} else {
    getNotNullField = item => item.SomeOtherField;
}

...

var itemsFromList = from item in ListItems where getNotNullField(item) != null 
                    select item;   
于 2012-06-13T13:37:58.790 に答える