В Вашем сравнении между IEnumerable<int>
и IEnumerable<double>
Вы не должны волноваться - при передаче неправильного типа код не скомпилирует так или иначе.
нет никакой озабоченности по поводу безопасности типов, как var
не динамичные. Это - просто волшебство компилятора и любой тип небезопасные вызовы, Вы составляете завещание, пойманы.
Var
абсолютно необходим для Linq:
var anonEnumeration =
from post in AllPosts()
where post.Date > oldDate
let author = GetAuthor( post.AuthorId )
select new {
PostName = post.Name,
post.Date,
AuthorName = author.Name
};
Теперь взгляд anonEnumeration в intellisense и это появится что-то как IEnumerable<'a>
foreach( var item in anonEnumeration )
{
//VS knows the type
item.PostName; //you'll get intellisense here
//you still have type safety
item.ItemId; //will throw a compiler exception
}
, компилятор C# довольно умен - скоро вводит сгенерированный, отдельно будет иметь тот же сгенерированный тип, если их свойства будут соответствовать.
За пределами этого, пока у Вас есть intellisense, который это проявляет здравый смысл использовать var
где угодно, контекст ясен.
//less typing, this is good
var myList = new List<UnreasonablyLongClassName>();
//also good - I can't be mistaken on type
var anotherList = GetAllOfSomeItem();
//but not here - probably best to leave single value types declared
var decimalNum = 123.456m;
С точки зрения организации, изучение API-интерфейсов POSIX , особенно потоков pthread , даст вам хорошее представление о том, как организовать код C. Основные правила хорошей организации проекта C:
Я был в основном в той же лодке, что и вы (хотя и с меньшим опытом, и я начал с Python, а не с Java), и мне больше всего удавалось сидеть и читать Кернигана и Ричи. Вы сможете бегло просмотреть первую половину книги, так как вам понятен синтаксис, но вы определенно уйдете, лучше понимая низкоуровневое управление памятью.
Чтение частей ядра Linux источник, связанный с управлением памятью, также помогает, но не для слабонервных или легко скучающих.
В любом случае, я считаю, что изучение построения программ с широким использованием указателей и низкоуровневых структур было бы хорошим началом. Это также зависит от того, для чего построена программа. Вы пытаетесь написать код C на встроенной плате rtos или системе микроконтроллера?
Вы также можете проверить Язык программирования C ANSI C Edition , написанный Керниганом и Ричи. Да, он старый, но он занимает примерно 200 страниц и охватывает весь язык, а также стандартную библиотеку.
Расширяя другой ответ , можно просто писать объектно-ориентированный язык C. Именно так ведет себя большинство библиотек, с которыми я взаимодействую (например, стек GNOME почти полностью является объектно-ориентированным C, в основном на основе библиотеки gobject, чтобы упростить задачу). Вы можете думать об этом как о C ++ без некоторого синтаксического сахара.
В итоге вы получаете API вроде
/* in project NewStuff; namespace is ns */
ns_foo_t *ns_foo_new ();
void ns_foo_delete (ns_foo_t *);
int ns_foo_make_waffles (ns_foo_t *this, int no_of_guests);
int main () {
ns_foo_t *my_foo = ns_foo_new ();
ns_foo_make_waffles (my_foo, 1);
ns_foo_delete (my_foo);
}
, который почти точно соответствует
class Foo {
public:
Foo () { /* whatever */ }
int make_waffles (int no_of_guests) {}
};
int main () {
Foo *my_foo = new Foo ();
my_foo->make_waffles (1);
delete my_foo;
}