In Which @Captain asks C# Beginner Questions
-
@lucas1 if they do the same thing, I would say there shouldn't even be a close!
-
@Magus https://blogs.msdn.microsoft.com/kimhamil/2008/03/15/the-often-non-difference-between-close-and-dispose/
Apparently they can do different things depending on implementation. I didn't know that.
-
@dkf I think on unix there isn't even a foolproof method, as
argv[0]
is not reliable. It may be absolute, it may be relevant to some item of$PATH
, but there may also be complete garbage in there as the binary to invoke is a completely separate argument toexec
.
-
@PleegWat said in In Which @Captain asks C# Beginner Questions:
I think on unix there isn't even a foolproof method, as argv[0] is not reliable.
That's true, but there are ways that work on many key platforms. For example, I think you can read it out of somewhere inside
/proc
on Linux. There's just no standard method.OTOH, re-resolving
argv[0]
against thePATH
mostly works too. Except for login shells or where someone has decided to be determinedly nasty in how they invoke you. (That last one is rare.) I vaguely remember that some platforms allow you to rewriteargv[0]
for various purposes too, but if that causes problems for people wanting to know where the process executable is, they're idiots and the authors of their own misfortune.
-
@dkf I do have a binary lying around somewhere which starts with something like:
int main(int argc, char * argv[]) { char * arg = argc > 1 ? argv[1] : NULL; chdir("/"); clearenv(); /* validate the bejeeves out of arg */ realmain(arg); }
-
@Captain said in In Which @Captain asks C# Beginner Questions:
C# doesn't care which I type.
Course it doesn't. Any whitespace-agnostic language should be fine.
So basically, not Python
-
@sloosecannon said in In Which @Captain asks C# Beginner Questions:
So basically, not Python
And not Haskell either. There are a few other languages that have an โinterestingโ relationship with newline too, though they wouldn't have problems in the equivalent of this case.
-
@dkf Haskell definitely lets me do prefixed commas.
-
@Captain Because there's additional syntax that means that the parser knows that it's not got a complete phrase.
-
@sloosecannon said in In Which @Captain asks C# Beginner Questions:
So basically, not Python
def wrong(): return ["is" ,"what" ,"you" ,"are"]
(Python allows a statement to span multiple lines with arbitrary extra indentation as long as there's either an unclosed paren/bracket/brace (like above), or "\" is used to force it.)
Of course, like in C# and any other non-antique language worth a damn, you can/should just use trailing commas.
So what is that mythical language that doesn't support these "prefixed" commas?
-
@Magus said in In Which @Captain asks C# Beginner Questions:
Additionally, it's generally preferred to use the keyword forms of built in types when possible, as then there is no risk of someone reusing the class name.
Your code should use keyword forms, but any method names, since they might be consumed by non-C# languages, should use the class name. (GetAsInt64(), not GetAsLong().)
-
This is what my
Main
looks like right now. Any thoughts or comments?static void Main(string[] args) { String result = System.String.Empty; const int port = 22; const string host = "domainna.me"; const string username = "chucknorris"; const string password = "norrischuck"; const string workingdirectory = "/highway/hell"; string filename = "STATUS" + facilityId.PadLeft(15, '0') + now.ToString("yyyymmddHHmmss"); using (var dbConn = new SqlConnection(Properties.Settings.Default.PsychAdvantageConnectionString)) using (var sqlQuery = new StreamReader( Path.Combine(Application.StartupPath, "status.sql"), Encoding.UTF8) ) { // run the query dbConn.Open(); IEnumerable<dynamic> patients = dbConn.Query<dynamic>(sqlQuery.ReadToEnd()); PutHeading(); foreach (dynamic patient in patients) { // format each row; PutStatus(patient); } dbConn.Close(); } using (var sftp = new SftpClient(host, port, username, password)) using (var resultStream = new MemoryStream(Encoding.UTF8.GetBytes(result))) { // upload the file Console.WriteLine("Creating sftp client and connecting."); sftp.Connect(); Console.WriteLine("Connected to {0}", host); sftp.ChangeDirectory(workingdirectory); Console.WriteLine("Changed directory to {0}", workingdirectory); Console.WriteLine("Uploading MOTS results ({0:N0} bytes)", resultStream.Length); sftp.BufferSize = 4 * 1024; // bypass Payload error large files sftp.UploadFile(resultStream, workingdirectory + "/" + filename); } }
I am finding that I don't like the dynamic-ness of the patients, since it means I have no idea how many type errors I will have to fix at run-time when I'm done with the list of fields to implement.
Given the discussion above about
using
andIDisposable
andClose
, I guess I can get rid of the manual call to closing thedbConn
.
-
@Captain I try to use string.Format() rather than concatenation when possible so I'd write
string filename = "STATUS" + facilityId.PadLeft(15, '0') + now.ToString("yyyymmddHHmmss");
as
string filename = string.Format("STATUS{0:d15}{1:yyyyMMddHHmmss}", facilityId, now);
that allows you to put your formatting right in the template string as well.
edit: in dates "mm" is minutes and "MM" is months
-
@Captain I've never done dynamic sql results. Typically I'll define a class ahead of time to match the data coming in, use a SqlDataReader to read in records and populate the instances of the class, then return a list.
-
@fwd said in In Which @Captain asks C# Beginner Questions:
edit: in dates "mm" is minutes and "MM" is months
Yeah, good tip. In related news, VS has a shitty
Find...
UI.
-
@Captain I would highly recommend against using
dynamic
. It's basically a keyword that says, "instead of checking type errors at compile-time, let's fuck the user over at run-time". Frankly I don't think it should have been added to the language.Apparently it's intended for COM interop stuff.
-
would someone from Haskell use
dynamic
anyway?
-
@Magus Because ADO.NET can't type check against this dumb database engine's schema. (It's the database's fault).
-
@Captain Are you calling a SPROC that can return variable result sets? Those are... tricky.
Once you get a DataTable, you can pull the data from it into your class any way you want. I'd recommend making a C# POCO class with the items you know you need, and write a quick method to yank those items out of the DataRow and ignore the rest.
-
@Captain Your method are too long.
-
@lucas1 I'd agree, but this seems to be a tiny console app, which I'm inclined to give more freedoms: I don't need a bunch of short methods or classes in EdgeMasterZero9000 (My horrible name generator)
-
I wasn't being 100% serious
-
@lucas1 Speaking of which:
class Program { private static Random random = new Random(); static void Main(string[] args) { Console.WriteLine("How much edge can you take? (max word number)"); int wordCount; if (!Int32.TryParse(Console.ReadLine(), out wordCount)) return; IEnumerable<string> names; using (var contents = typeof (Program).Assembly.GetManifestResourceStream("EdgeMasterZero9000.Edge.txt")) { var reader = new StreamReader(contents); var all = reader.ReadToEnd(); names = all.Split(new []{Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries); } while (true) { Console.WriteLine("Your name is:"); Console.WriteLine(PickWords(wordCount, names.ToList())); // generated Console.WriteLine("Press any key to generate again!"); Console.ReadKey(); } } private static string PickWords(int number, List<string> words) { var shuffled = new List<string>(); while (words.Any()) { var toRemove = random.Next(0, words.Count); shuffled.Add(words[toRemove]); words.RemoveAt(toRemove); } var result = string.Empty; for (int i = 0; i < number; i++) { result += shuffled[i]; } return result; } }
Fire Blade Destroyer God Apocalypse Demon Angel Arch Zero Ultra Omega Alpha Mega Blood Lord Axe War Lich Fallen Killer Infinity Dark Flame Burning Burner Metal Harbinger Maelstrom Zephyr Paradox Omni Oblivion Nexus Monolith Death Ghost Equinox Requiem Zenith Aeon Pain Doom Shadow Cleave Kirito Power
Old, but it even has an embedded resource!
-
@Magus said in In Which @Captain asks C# Beginner Questions:
private static Random random = new Random();
I always loved this line of code.
Then I made a multi-threaded Random class and alas I no longer use it.
-
@blakeyrat No, I'm not using an sproc. I basically don't have write access to the database schema, so I can't make a view or sproc that has all the columns my query needs.
Maybe things have changes in the last few months (since I picked out how I would do the query), but there were good raisins for why I picked
dynamic
Dapper. (That said, I'd love to move away from the dynamic keyword). I'll take a look at Dapper again.
-
@Captain dynamic is pure evil, if you use it:
https://www.youtube.com/watch?v=P6J352J_RG8
This is what happens.
In all seriousness try to avoid it if at all possible. Kinda defeats the point of C#
-
@lucas1 said in In Which @Captain asks C# Beginner Questions:
Kinda defeats the point of C#
Right, right?
Sure it makes COM interop a slight bit easier, I guess, only for shitty COM components.
But it's like totally the opposite of what everything C# is designed to do and be. If there's ONE THING that makes C# C#, it's that it's strongly-typed as shit and its compiler will catch EVERY type error, fuck you programmer you can't slip that one past!
-
@blakeyrat While I agree, you're posting that in the thread of a Haskell user.
-
@Magus I suppose that comment would have some meaning to me if I knew absolutely anything whatsoever about Haskell?
-
@blakeyrat It's main claim to fame is it's typing, which is meant to make most issues in code become type issues and not compile if it has any.
-
Haskell is also statically typed, and its type language is much (much) more expressive (i.e., the type language is stronger than C#'s).
Haskell's types are fully algebraic, and parametric polymorphism makes code a lot easier to reason about. Multi-parameter type classes are like C# interfaces, except the interface can depend on multiple types. Etc.
-
@Captain don't even know what that means, since you seem to imply that its something different than multi-generic interfaces, which can themselves depend on any number of interfaces.
-
A monomorphic type class would be something along the lines of:
class IsString obj where toString :: obj -> String fromString :: String -> Maybe obj
So you can see that the
obj
can be turned into aString
with thetoString
method and thefromString
method parses aString
toMaybe
return anobj
.The translation to C# interfaces is straight-forward.
But now consider a multi-parameter type class like:
class Store store m where new :: a -> m (store a) get :: store a -> m a put :: store a -> a -> m ()
That is a "multi-param type class", and it lets method resolution depend on more than one type. You can use multi-param type classes to implement things like relations and functions at the type level.
-
@fwd said in In Which @Captain asks C# Beginner Questions:
@Captain I try to use string.Format() rather than concatenation when possible so I'd write
string filename = "STATUS" + facilityId.PadLeft(15, '0') + now.ToString("yyyymmddHHmmss");
as
string filename = string.Format("STATUS{0:d15}{1:yyyyMMddHHmmss}", facilityId, now);
that allows you to put your formatting right in the template string as well.
edit: in dates "mm" is minutes and "MM" is months
Or in C# 6, you can use string interpolation:
string filename = $"STATUS{facilityId:d15}{now:yyyyMMddHHmmss}";
-
@Captain said in In Which @Captain asks C# Beginner Questions:
Any thoughts or comments?
:cough: Why are you uploading an empty byte array? (You never assign to
result
.)ETA: also, you declared result as
String
instead ofstring
, which isn't wrong, but is inconsistent with the other declarations (which use the lower-case version) and isn't preferred style.
-
This post is deleted!
-
@Dreikin said in In Which @Captain asks C# Beginner Questions:
Or in C# 6, you can use string interpolation:
string filename = $"STATUS{facilityId:d15}{now:yyyyMMddHHmmss}";
That looks dangerously close to php bullshit.
-
@Captain showing off the syntax of something no one else knows isn't a good way to explain a thing no one else knows. And again:
T DoThing<T, U>(T t) where T : IEnumerable<U>
Is possibly similar.
-
This post is deleted!
-
@error Pft, not even going to acknowledge the ? ;)
-
Accidentally said the same thing @Dreikin said. That'll teach me to post before reading.
-
@error then you changed to something I said?
-
@fbmac said in In Which @Captain asks C# Beginner Questions:
@error then you changed to something I said?
no, he changed to something you unsaid.
-
@Magus said in In Which @Captain asks C# Beginner Questions:
showing off the syntax of something no one else knows isn't a good way to explain a thing no one else knows
Yeah, I tried to work that out then gave up
-
waiting anxiously for @captain to make an intermediate or advanced question so I can complain he is going off topic
-
@Captain said in In Which @Captain asks C# Beginner Questions:
That is a "multi-param type class", and it lets method resolution depend on more than one type. You can use multi-param type classes to implement things like relations and functions at the type level.
So what's the difference to an interface with more than one type parameter? It's been too long since I last used Haskell, so I can't figure out what your example means.
-
Is the real part of all non-trivial zeroes of the Riemann zeta function equal to 1/2?
Does P=NP?
-
@error you're triple offtopic here:
- you're not @captain
- this isn't a beginner's question
- it's not about C#
-
@asdf said in In Which @Captain asks C# Beginner Questions:
So what's the difference to an interface with more than one type parameter? It's been too long since I last used Haskell, so I can't figure out what your example means.
Actually, I didn't know C# had interfaces with more than one parameter.
So I'll just say this: I come from a language with very strong typing and I don't know this language well enough to compare it. But Haskell has at least as strong a type system. That's what it's for -- it's a research language for type theory, and it finds some use in some industries because of the paranoid levels of typing you can achieve.
-
@Captain It's important to note that type parameters are a totally separate thing from interfaces. They can be on classes, structs, interfaces, abstract classes, or even just methods. On the type level, they don't support type inference, but in methods, they do. In any of those places, you can have as many as you want.