#c# #linq
#c# #linq
Вопрос:
я попытался взять одну запись и пропустить остальные. мой код не выдает никакой ошибки, но и не выдает никаких выходных данных. вот мой код. поэтому, пожалуйста, взгляните и скажите мне, что не так в моем коде.
public sealed class Person
{
public Person() { }
public Person(string name,bool HQ) {
this.Name = name;
this.HQ = HQ;
}
private string _Name;
public string Name
{
get { return _Name; }
set { _Name = value; }
}
private bool _HQ;
public bool HQ
{
get { return _HQ; }
set { _HQ = value; }
}
}
protected void btn_Click(object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt.Columns.Add("Name",typeof(string));
dt.Columns.Add("HQ", typeof(bool));
DataRow dr = null;
dr = dt.NewRow();
dr["Name"]="Arijit";
dr["HQ"]=true;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["Name"] = "Dibyendu";
dr["HQ"] = false;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["Name"] = "Tridip";
dr["HQ"] = false;
dt.Rows.Add(dr);
List<Person> oPerson1 = (from c in dt.AsEnumerable()
select new Person
{
Name = c.Field<string>("Name"),
HQ = c.Field<bool>("HQ")
}).Skip(1).Take(2).ToList();
List<Person> oPerson2 = (from c in dt.AsEnumerable()
select new Person
{
Name = c.Field<string>("Name"),
HQ = c.Field<bool>("HQ")
}).Take(1).Skip(2).ToList();
}
Ответ №1:
если вы хотите взять первую запись, вы можете вызвать эти Take(1)
, First()
, FirstOrDefault()
если вы хотите взять 1 запись в середине, вызовите это: Skip(n).Take(1)
где n
— количество пропущенных записей
Когда вы вызываете Take(n)
— нет необходимости вызывать Skip после этого, он уже выбрал n записей
Комментарии:
1. Важное различие.
Take
возвращаетIEnumerable<TSource>
иFirst
возвращаетTSource
.
Ответ №2:
Попробуйте этот код.
Person oPerson1 = (from c in dt.AsEnumerable()
select new Person
{
Name = c.Field<string>("Name"),
HQ = c.Field<bool>("HQ")
}).First(); //first person in a list
Person oPerson2 = (from c in dt.AsEnumerable()
select new Person
{
Name = c.Field<string>("Name"),
HQ = c.Field<bool>("HQ")
}).Skip(1).First(); //second person in a list
However this code can be rewritten to be clearer:
List<Person> persons = from c in dt.AsEnumerable()
select new Person
{
Name = c.Field<string>("Name"),
HQ = c.Field<bool>("HQ")
};
Person oPerson1 = persons[0];
Person oPerson2 = persons[1];
Ответ №3:
Я предпочитаю использовать IQueryable
, а не List
.
В любом случае вы можете использовать Queryable.Пропустите, чтобы пропустить количество элементов, которые вам нужны
IQueryable<Person> oPerson2 = (from c in dt.AsEnumerable()
select new Person
{
Name = c.Field<string>("Name"),
HQ = c.Field<bool>("HQ")
}).Skip(2).Take(1);
Также вы найдете больше об этом в Возвращать или пропускать элементы в последовательности (LINQ to SQL)
Ответ №4:
Я не уверен, что вы подразумеваете под «возьмите одну и пропустите остальные», но я подозреваю, что вы путаете, как работают операции LINQ. Они возвращают новую последовательность на основе указанных вами критериев, и эта новая последовательность содержит только то, что вы просили.
Например, если у вас есть список с тремя элементами, и вы вызвали Take(1)
, вы получите обратно IEnumerable с 1 элементом. «Пропускать» больше нечего, потому что в вашем списке есть только один элемент. Ваша исходная таблица данных остается неизменной — последовательности LINQ неизменяемы.
Похоже, все, что вы действительно хотите сделать, это:
List<Person> oPerson2 = (from c in dt.AsEnumerable()
select new Person
{
Name = c.Field<string>("Name"),
HQ = c.Field<bool>("HQ")
}).Take(1).ToList();
Конечно, это очень распространенная операция в LINQ, поэтому есть другой, несколько «более понятный» способ сделать это:
Person oPerson2 = (from c in dt.AsEnumerable()
select new Person
{
Name = c.Field<string>("Name"),
HQ = c.Field<bool>("HQ")
}).First();
Ответ №5:
Если вы хотите получить только одну запись, вам следует заменить вызов final ToList на First()
или FirstOrDefault()
они здесь как раз для этой цели. Разница между двумя методами заключается в том, First()
что они генерируют исключение, если нечего возвращать (например, пустую коллекцию). И FirstOrDefault()
вернет default(T)
(например, null для классов и 0 для типов значений).
Ответ №6:
Разбивая цепочку, затем:
List<Person> oPerson2 = (from c in dt.AsEnumerable()
select new Person
{
Name = c.Field<string>("Name"),
HQ = c.Field<bool>("HQ")
}).Take(1).Skip(2).ToList();
становится:
var tmp0 = (from c in dt.AsEnumerable()
select new Person
{
Name = c.Field<string>("Name"),
HQ = c.Field<bool>("HQ")
});
var tmp1 = tmp0.Take(1);
var tmp2 = tmp1.Skip(2);
List<Person> oPerson2 = tmp2.ToList();
Это облегчает обнаружение ошибки. tmp0 — это перечисляемый параметр, который при перечислении вернет все возможные строки. tmp1 — это перечисляемый параметр, который вернет только первую 1 строку в tmp0 (или меньше, если строк недостаточно). tmp2 — это перечисляемый параметр, который пропустит первые 2 строки в tmp1 (или меньше, если строк недостаточно), а затем вернет остальные. Наконец, oPerson2 заставляет эти перечислимые объекты фактически возвращать свои результаты и сохраняет их в списке.
Из этого ясно, что ошибка была .Skip(2)
в том, что она использует перечисление из одного элемента, пропускает до 2 и оставляет остальное, в результате чего получается список из max (1 — 2, 0) = 0 элементов.
Не учитывайте Skip()
, и вы получите то, что хотите, поскольку «взять до 1» уже влечет за собой «пропустить остальное».
Ответ №7:
Также .Для достижения этого можно использовать First()
List<X> xlist= XBusiness.GetAllX(xname.ToString());
X lastX = xlist.First();