Replacing Uri with a more convenient class











up vote
0
down vote

favorite












I needed some data structure for holding Uris so I thought I try the Uri class. It quickly turned out that it's very impractical because:




  • it's missing an implicit cast from/to string

  • it doesn't automatically recognize uris as absolute or relative without specifying the UriKind

  • it doesn't parse the query-string so it cannot compare uris reliably when key-value pairs are in different order

  • it's not easy to combine an absolute uri with a relative one


Working with it is just too inconvenient. As a solution I created my own SimpleUri that should solve these issues. It doesn't support everything yet because I don't need it right now but adding a couple of more regexes later should be a problem.



public class SimpleUri : IEquatable<SimpleUri>, IEquatable<string>
{
// https://regex101.com/r/sd288W/1
// using 'new' for _nicer_ syntax
private static readonly string UriPattern = string.Join(string.Empty, new
{
/* language=regexp */ @"^(?:(?<scheme>w+):)?",
/* language=regexp */ @"(?://(?<authority>w+))?",
/* language=regexp */ @"(?<path>[a-z0-9/:]+)",
/* language=regexp */ @"(?:?(?<query>[a-z0-9=&]+))?",
/* language=regexp */ @"(?:#(?<fragment>[a-z0-9]+))?"
});

public static readonly IEqualityComparer<SimpleUri> Comparer = EqualityComparerFactory<SimpleUri>.Create
(
equals: (x, y) => StringComparer.OrdinalIgnoreCase.Equals(x, y),
getHashCode: (obj) => StringComparer.OrdinalIgnoreCase.GetHashCode(obj)
);

public SimpleUri([NotNull] string uri)
{
if (uri == null) throw new ArgumentNullException(nameof(uri));

var uriMatch = Regex.Match
(
uri,
UriPattern,
RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture
);

if (!uriMatch.Success)
{
throw new ArgumentException(paramName: nameof(uri), message: $"'{uri}' is not a valid Uri.");
}

Scheme = uriMatch.Groups["scheme"];
Authority = uriMatch.Groups["authority"];
Path = uriMatch.Groups["path"];
Query =
uriMatch.Groups["query"].Success
? Regex
.Matches
(
uriMatch.Groups["query"].Value,
@"(?:^|&)(?<key>[a-z0-9]+)(?:=(?<value>[a-z0-9]+))?",
RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture
)
.Cast<Match>()
.ToImmutableDictionary
(
m => (ImplicitString)m.Groups["key"],
m => (ImplicitString)m.Groups["value"]
)
: ImmutableDictionary<ImplicitString, ImplicitString>.Empty;
Fragment = uriMatch.Groups["fragment"];
}

public SimpleUri(SimpleUri absoluteUri, SimpleUri relativeUri)
{
if (absoluteUri.IsRelative) throw new ArgumentException($"{nameof(absoluteUri)} must be an absolute Uri.");
if (!relativeUri.IsRelative) throw new ArgumentException($"{nameof(relativeUri)} must be a relative Uri.");

Scheme = absoluteUri.Scheme;
Authority = absoluteUri.Authority;
Path = absoluteUri.Path.Value.TrimEnd('/') + "/" + relativeUri.Path.Value.TrimStart('/');
Query = absoluteUri.Query;
Fragment = absoluteUri.Fragment;
}

public ImplicitString Scheme { get; }

public ImplicitString Authority { get; }

public ImplicitString Path { get; }

public IImmutableDictionary<ImplicitString, ImplicitString> Query { get; }

public ImplicitString Fragment { get; }

public bool IsRelative => !Scheme;

public override string ToString() => string.Join(string.Empty, GetComponents());

private IEnumerable<string> GetComponents()
{
if (Scheme)
{
yield return $"{Scheme}:";
}

if (Authority)
{
yield return $"//{Authority}";
}

yield return Path;

if (Query.Any())
{
var queryPairs =
Query
.OrderBy(x => (string)x.Key, StringComparer.OrdinalIgnoreCase)
.Select(x => $"{x.Key}{(x.Value ? "=" : string.Empty)}{x.Value}");
yield return $"?{string.Join("&", queryPairs)}";
}

if (Fragment)
{
yield return $"#{Fragment}";
}
}

#region IEquatable

public bool Equals(SimpleUri other) => Comparer.Equals(this, other);

public bool Equals(string other) => Comparer.Equals(this, other);

public override bool Equals(object obj) => obj is SimpleUri uri && Equals(uri);

public override int GetHashCode() => Comparer.GetHashCode(this);

#endregion

#region operators

public static implicit operator SimpleUri(string uri) => new SimpleUri(uri);

public static implicit operator string(SimpleUri uri) => uri.ToString();

public static SimpleUri operator +(SimpleUri absoluteUri, SimpleUri relativeUri) => new SimpleUri(absoluteUri, relativeUri);

#endregion
}


In this experiment I use a new helper for the first time which is the ImplicitString. Its purpose is to be able to use a string as a conditional without having to write any of the string.IsX all over the place.



public class ImplicitString : IEquatable<ImplicitString>
{
public ImplicitString(string value) => Value = value;

[AutoEqualityProperty]
public string Value { get; }

public override string ToString() => Value;

public static implicit operator ImplicitString(string value) => new ImplicitString(value);

public static implicit operator ImplicitString(Group group) => group.Value;

public static implicit operator string(ImplicitString value) => value.ToString();

public static implicit operator bool(ImplicitString value) => !string.IsNullOrWhiteSpace(value);

#region IEquatable

public bool Equals(ImplicitString other) => AutoEquality<ImplicitString>.Comparer.Equals(this, other);

public override bool Equals(object obj) => obj is ImplicitString str && Equals(str);

public override int GetHashCode() => AutoEquality<ImplicitString>.Comparer.GetHashCode(this);

#endregion
}


Example



I tested it with use-cases I currently need it for and it works fine:



new SimpleUri("scheme://authority/p/a/t/h?query#fragment").Dump();
new SimpleUri("scheme:p/a/t/h?q1=v1&q2=v2&q3#fragment").Dump();
new SimpleUri("p/a/t/h?q1=v1&q2=v2&q3#fragment").Dump();
new SimpleUri("p/a/t/h").Dump();
new SimpleUri("file:c:/p/a/t/h").Dump();




What do you say? Is this an optimal implementation or can it be improved?










share|improve this question
























  • The EqualityComparerFactory can be found here.
    – t3chb0t
    2 hours ago















up vote
0
down vote

favorite












I needed some data structure for holding Uris so I thought I try the Uri class. It quickly turned out that it's very impractical because:




  • it's missing an implicit cast from/to string

  • it doesn't automatically recognize uris as absolute or relative without specifying the UriKind

  • it doesn't parse the query-string so it cannot compare uris reliably when key-value pairs are in different order

  • it's not easy to combine an absolute uri with a relative one


Working with it is just too inconvenient. As a solution I created my own SimpleUri that should solve these issues. It doesn't support everything yet because I don't need it right now but adding a couple of more regexes later should be a problem.



public class SimpleUri : IEquatable<SimpleUri>, IEquatable<string>
{
// https://regex101.com/r/sd288W/1
// using 'new' for _nicer_ syntax
private static readonly string UriPattern = string.Join(string.Empty, new
{
/* language=regexp */ @"^(?:(?<scheme>w+):)?",
/* language=regexp */ @"(?://(?<authority>w+))?",
/* language=regexp */ @"(?<path>[a-z0-9/:]+)",
/* language=regexp */ @"(?:?(?<query>[a-z0-9=&]+))?",
/* language=regexp */ @"(?:#(?<fragment>[a-z0-9]+))?"
});

public static readonly IEqualityComparer<SimpleUri> Comparer = EqualityComparerFactory<SimpleUri>.Create
(
equals: (x, y) => StringComparer.OrdinalIgnoreCase.Equals(x, y),
getHashCode: (obj) => StringComparer.OrdinalIgnoreCase.GetHashCode(obj)
);

public SimpleUri([NotNull] string uri)
{
if (uri == null) throw new ArgumentNullException(nameof(uri));

var uriMatch = Regex.Match
(
uri,
UriPattern,
RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture
);

if (!uriMatch.Success)
{
throw new ArgumentException(paramName: nameof(uri), message: $"'{uri}' is not a valid Uri.");
}

Scheme = uriMatch.Groups["scheme"];
Authority = uriMatch.Groups["authority"];
Path = uriMatch.Groups["path"];
Query =
uriMatch.Groups["query"].Success
? Regex
.Matches
(
uriMatch.Groups["query"].Value,
@"(?:^|&)(?<key>[a-z0-9]+)(?:=(?<value>[a-z0-9]+))?",
RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture
)
.Cast<Match>()
.ToImmutableDictionary
(
m => (ImplicitString)m.Groups["key"],
m => (ImplicitString)m.Groups["value"]
)
: ImmutableDictionary<ImplicitString, ImplicitString>.Empty;
Fragment = uriMatch.Groups["fragment"];
}

public SimpleUri(SimpleUri absoluteUri, SimpleUri relativeUri)
{
if (absoluteUri.IsRelative) throw new ArgumentException($"{nameof(absoluteUri)} must be an absolute Uri.");
if (!relativeUri.IsRelative) throw new ArgumentException($"{nameof(relativeUri)} must be a relative Uri.");

Scheme = absoluteUri.Scheme;
Authority = absoluteUri.Authority;
Path = absoluteUri.Path.Value.TrimEnd('/') + "/" + relativeUri.Path.Value.TrimStart('/');
Query = absoluteUri.Query;
Fragment = absoluteUri.Fragment;
}

public ImplicitString Scheme { get; }

public ImplicitString Authority { get; }

public ImplicitString Path { get; }

public IImmutableDictionary<ImplicitString, ImplicitString> Query { get; }

public ImplicitString Fragment { get; }

public bool IsRelative => !Scheme;

public override string ToString() => string.Join(string.Empty, GetComponents());

private IEnumerable<string> GetComponents()
{
if (Scheme)
{
yield return $"{Scheme}:";
}

if (Authority)
{
yield return $"//{Authority}";
}

yield return Path;

if (Query.Any())
{
var queryPairs =
Query
.OrderBy(x => (string)x.Key, StringComparer.OrdinalIgnoreCase)
.Select(x => $"{x.Key}{(x.Value ? "=" : string.Empty)}{x.Value}");
yield return $"?{string.Join("&", queryPairs)}";
}

if (Fragment)
{
yield return $"#{Fragment}";
}
}

#region IEquatable

public bool Equals(SimpleUri other) => Comparer.Equals(this, other);

public bool Equals(string other) => Comparer.Equals(this, other);

public override bool Equals(object obj) => obj is SimpleUri uri && Equals(uri);

public override int GetHashCode() => Comparer.GetHashCode(this);

#endregion

#region operators

public static implicit operator SimpleUri(string uri) => new SimpleUri(uri);

public static implicit operator string(SimpleUri uri) => uri.ToString();

public static SimpleUri operator +(SimpleUri absoluteUri, SimpleUri relativeUri) => new SimpleUri(absoluteUri, relativeUri);

#endregion
}


In this experiment I use a new helper for the first time which is the ImplicitString. Its purpose is to be able to use a string as a conditional without having to write any of the string.IsX all over the place.



public class ImplicitString : IEquatable<ImplicitString>
{
public ImplicitString(string value) => Value = value;

[AutoEqualityProperty]
public string Value { get; }

public override string ToString() => Value;

public static implicit operator ImplicitString(string value) => new ImplicitString(value);

public static implicit operator ImplicitString(Group group) => group.Value;

public static implicit operator string(ImplicitString value) => value.ToString();

public static implicit operator bool(ImplicitString value) => !string.IsNullOrWhiteSpace(value);

#region IEquatable

public bool Equals(ImplicitString other) => AutoEquality<ImplicitString>.Comparer.Equals(this, other);

public override bool Equals(object obj) => obj is ImplicitString str && Equals(str);

public override int GetHashCode() => AutoEquality<ImplicitString>.Comparer.GetHashCode(this);

#endregion
}


Example



I tested it with use-cases I currently need it for and it works fine:



new SimpleUri("scheme://authority/p/a/t/h?query#fragment").Dump();
new SimpleUri("scheme:p/a/t/h?q1=v1&q2=v2&q3#fragment").Dump();
new SimpleUri("p/a/t/h?q1=v1&q2=v2&q3#fragment").Dump();
new SimpleUri("p/a/t/h").Dump();
new SimpleUri("file:c:/p/a/t/h").Dump();




What do you say? Is this an optimal implementation or can it be improved?










share|improve this question
























  • The EqualityComparerFactory can be found here.
    – t3chb0t
    2 hours ago













up vote
0
down vote

favorite









up vote
0
down vote

favorite











I needed some data structure for holding Uris so I thought I try the Uri class. It quickly turned out that it's very impractical because:




  • it's missing an implicit cast from/to string

  • it doesn't automatically recognize uris as absolute or relative without specifying the UriKind

  • it doesn't parse the query-string so it cannot compare uris reliably when key-value pairs are in different order

  • it's not easy to combine an absolute uri with a relative one


Working with it is just too inconvenient. As a solution I created my own SimpleUri that should solve these issues. It doesn't support everything yet because I don't need it right now but adding a couple of more regexes later should be a problem.



public class SimpleUri : IEquatable<SimpleUri>, IEquatable<string>
{
// https://regex101.com/r/sd288W/1
// using 'new' for _nicer_ syntax
private static readonly string UriPattern = string.Join(string.Empty, new
{
/* language=regexp */ @"^(?:(?<scheme>w+):)?",
/* language=regexp */ @"(?://(?<authority>w+))?",
/* language=regexp */ @"(?<path>[a-z0-9/:]+)",
/* language=regexp */ @"(?:?(?<query>[a-z0-9=&]+))?",
/* language=regexp */ @"(?:#(?<fragment>[a-z0-9]+))?"
});

public static readonly IEqualityComparer<SimpleUri> Comparer = EqualityComparerFactory<SimpleUri>.Create
(
equals: (x, y) => StringComparer.OrdinalIgnoreCase.Equals(x, y),
getHashCode: (obj) => StringComparer.OrdinalIgnoreCase.GetHashCode(obj)
);

public SimpleUri([NotNull] string uri)
{
if (uri == null) throw new ArgumentNullException(nameof(uri));

var uriMatch = Regex.Match
(
uri,
UriPattern,
RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture
);

if (!uriMatch.Success)
{
throw new ArgumentException(paramName: nameof(uri), message: $"'{uri}' is not a valid Uri.");
}

Scheme = uriMatch.Groups["scheme"];
Authority = uriMatch.Groups["authority"];
Path = uriMatch.Groups["path"];
Query =
uriMatch.Groups["query"].Success
? Regex
.Matches
(
uriMatch.Groups["query"].Value,
@"(?:^|&)(?<key>[a-z0-9]+)(?:=(?<value>[a-z0-9]+))?",
RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture
)
.Cast<Match>()
.ToImmutableDictionary
(
m => (ImplicitString)m.Groups["key"],
m => (ImplicitString)m.Groups["value"]
)
: ImmutableDictionary<ImplicitString, ImplicitString>.Empty;
Fragment = uriMatch.Groups["fragment"];
}

public SimpleUri(SimpleUri absoluteUri, SimpleUri relativeUri)
{
if (absoluteUri.IsRelative) throw new ArgumentException($"{nameof(absoluteUri)} must be an absolute Uri.");
if (!relativeUri.IsRelative) throw new ArgumentException($"{nameof(relativeUri)} must be a relative Uri.");

Scheme = absoluteUri.Scheme;
Authority = absoluteUri.Authority;
Path = absoluteUri.Path.Value.TrimEnd('/') + "/" + relativeUri.Path.Value.TrimStart('/');
Query = absoluteUri.Query;
Fragment = absoluteUri.Fragment;
}

public ImplicitString Scheme { get; }

public ImplicitString Authority { get; }

public ImplicitString Path { get; }

public IImmutableDictionary<ImplicitString, ImplicitString> Query { get; }

public ImplicitString Fragment { get; }

public bool IsRelative => !Scheme;

public override string ToString() => string.Join(string.Empty, GetComponents());

private IEnumerable<string> GetComponents()
{
if (Scheme)
{
yield return $"{Scheme}:";
}

if (Authority)
{
yield return $"//{Authority}";
}

yield return Path;

if (Query.Any())
{
var queryPairs =
Query
.OrderBy(x => (string)x.Key, StringComparer.OrdinalIgnoreCase)
.Select(x => $"{x.Key}{(x.Value ? "=" : string.Empty)}{x.Value}");
yield return $"?{string.Join("&", queryPairs)}";
}

if (Fragment)
{
yield return $"#{Fragment}";
}
}

#region IEquatable

public bool Equals(SimpleUri other) => Comparer.Equals(this, other);

public bool Equals(string other) => Comparer.Equals(this, other);

public override bool Equals(object obj) => obj is SimpleUri uri && Equals(uri);

public override int GetHashCode() => Comparer.GetHashCode(this);

#endregion

#region operators

public static implicit operator SimpleUri(string uri) => new SimpleUri(uri);

public static implicit operator string(SimpleUri uri) => uri.ToString();

public static SimpleUri operator +(SimpleUri absoluteUri, SimpleUri relativeUri) => new SimpleUri(absoluteUri, relativeUri);

#endregion
}


In this experiment I use a new helper for the first time which is the ImplicitString. Its purpose is to be able to use a string as a conditional without having to write any of the string.IsX all over the place.



public class ImplicitString : IEquatable<ImplicitString>
{
public ImplicitString(string value) => Value = value;

[AutoEqualityProperty]
public string Value { get; }

public override string ToString() => Value;

public static implicit operator ImplicitString(string value) => new ImplicitString(value);

public static implicit operator ImplicitString(Group group) => group.Value;

public static implicit operator string(ImplicitString value) => value.ToString();

public static implicit operator bool(ImplicitString value) => !string.IsNullOrWhiteSpace(value);

#region IEquatable

public bool Equals(ImplicitString other) => AutoEquality<ImplicitString>.Comparer.Equals(this, other);

public override bool Equals(object obj) => obj is ImplicitString str && Equals(str);

public override int GetHashCode() => AutoEquality<ImplicitString>.Comparer.GetHashCode(this);

#endregion
}


Example



I tested it with use-cases I currently need it for and it works fine:



new SimpleUri("scheme://authority/p/a/t/h?query#fragment").Dump();
new SimpleUri("scheme:p/a/t/h?q1=v1&q2=v2&q3#fragment").Dump();
new SimpleUri("p/a/t/h?q1=v1&q2=v2&q3#fragment").Dump();
new SimpleUri("p/a/t/h").Dump();
new SimpleUri("file:c:/p/a/t/h").Dump();




What do you say? Is this an optimal implementation or can it be improved?










share|improve this question















I needed some data structure for holding Uris so I thought I try the Uri class. It quickly turned out that it's very impractical because:




  • it's missing an implicit cast from/to string

  • it doesn't automatically recognize uris as absolute or relative without specifying the UriKind

  • it doesn't parse the query-string so it cannot compare uris reliably when key-value pairs are in different order

  • it's not easy to combine an absolute uri with a relative one


Working with it is just too inconvenient. As a solution I created my own SimpleUri that should solve these issues. It doesn't support everything yet because I don't need it right now but adding a couple of more regexes later should be a problem.



public class SimpleUri : IEquatable<SimpleUri>, IEquatable<string>
{
// https://regex101.com/r/sd288W/1
// using 'new' for _nicer_ syntax
private static readonly string UriPattern = string.Join(string.Empty, new
{
/* language=regexp */ @"^(?:(?<scheme>w+):)?",
/* language=regexp */ @"(?://(?<authority>w+))?",
/* language=regexp */ @"(?<path>[a-z0-9/:]+)",
/* language=regexp */ @"(?:?(?<query>[a-z0-9=&]+))?",
/* language=regexp */ @"(?:#(?<fragment>[a-z0-9]+))?"
});

public static readonly IEqualityComparer<SimpleUri> Comparer = EqualityComparerFactory<SimpleUri>.Create
(
equals: (x, y) => StringComparer.OrdinalIgnoreCase.Equals(x, y),
getHashCode: (obj) => StringComparer.OrdinalIgnoreCase.GetHashCode(obj)
);

public SimpleUri([NotNull] string uri)
{
if (uri == null) throw new ArgumentNullException(nameof(uri));

var uriMatch = Regex.Match
(
uri,
UriPattern,
RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture
);

if (!uriMatch.Success)
{
throw new ArgumentException(paramName: nameof(uri), message: $"'{uri}' is not a valid Uri.");
}

Scheme = uriMatch.Groups["scheme"];
Authority = uriMatch.Groups["authority"];
Path = uriMatch.Groups["path"];
Query =
uriMatch.Groups["query"].Success
? Regex
.Matches
(
uriMatch.Groups["query"].Value,
@"(?:^|&)(?<key>[a-z0-9]+)(?:=(?<value>[a-z0-9]+))?",
RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture
)
.Cast<Match>()
.ToImmutableDictionary
(
m => (ImplicitString)m.Groups["key"],
m => (ImplicitString)m.Groups["value"]
)
: ImmutableDictionary<ImplicitString, ImplicitString>.Empty;
Fragment = uriMatch.Groups["fragment"];
}

public SimpleUri(SimpleUri absoluteUri, SimpleUri relativeUri)
{
if (absoluteUri.IsRelative) throw new ArgumentException($"{nameof(absoluteUri)} must be an absolute Uri.");
if (!relativeUri.IsRelative) throw new ArgumentException($"{nameof(relativeUri)} must be a relative Uri.");

Scheme = absoluteUri.Scheme;
Authority = absoluteUri.Authority;
Path = absoluteUri.Path.Value.TrimEnd('/') + "/" + relativeUri.Path.Value.TrimStart('/');
Query = absoluteUri.Query;
Fragment = absoluteUri.Fragment;
}

public ImplicitString Scheme { get; }

public ImplicitString Authority { get; }

public ImplicitString Path { get; }

public IImmutableDictionary<ImplicitString, ImplicitString> Query { get; }

public ImplicitString Fragment { get; }

public bool IsRelative => !Scheme;

public override string ToString() => string.Join(string.Empty, GetComponents());

private IEnumerable<string> GetComponents()
{
if (Scheme)
{
yield return $"{Scheme}:";
}

if (Authority)
{
yield return $"//{Authority}";
}

yield return Path;

if (Query.Any())
{
var queryPairs =
Query
.OrderBy(x => (string)x.Key, StringComparer.OrdinalIgnoreCase)
.Select(x => $"{x.Key}{(x.Value ? "=" : string.Empty)}{x.Value}");
yield return $"?{string.Join("&", queryPairs)}";
}

if (Fragment)
{
yield return $"#{Fragment}";
}
}

#region IEquatable

public bool Equals(SimpleUri other) => Comparer.Equals(this, other);

public bool Equals(string other) => Comparer.Equals(this, other);

public override bool Equals(object obj) => obj is SimpleUri uri && Equals(uri);

public override int GetHashCode() => Comparer.GetHashCode(this);

#endregion

#region operators

public static implicit operator SimpleUri(string uri) => new SimpleUri(uri);

public static implicit operator string(SimpleUri uri) => uri.ToString();

public static SimpleUri operator +(SimpleUri absoluteUri, SimpleUri relativeUri) => new SimpleUri(absoluteUri, relativeUri);

#endregion
}


In this experiment I use a new helper for the first time which is the ImplicitString. Its purpose is to be able to use a string as a conditional without having to write any of the string.IsX all over the place.



public class ImplicitString : IEquatable<ImplicitString>
{
public ImplicitString(string value) => Value = value;

[AutoEqualityProperty]
public string Value { get; }

public override string ToString() => Value;

public static implicit operator ImplicitString(string value) => new ImplicitString(value);

public static implicit operator ImplicitString(Group group) => group.Value;

public static implicit operator string(ImplicitString value) => value.ToString();

public static implicit operator bool(ImplicitString value) => !string.IsNullOrWhiteSpace(value);

#region IEquatable

public bool Equals(ImplicitString other) => AutoEquality<ImplicitString>.Comparer.Equals(this, other);

public override bool Equals(object obj) => obj is ImplicitString str && Equals(str);

public override int GetHashCode() => AutoEquality<ImplicitString>.Comparer.GetHashCode(this);

#endregion
}


Example



I tested it with use-cases I currently need it for and it works fine:



new SimpleUri("scheme://authority/p/a/t/h?query#fragment").Dump();
new SimpleUri("scheme:p/a/t/h?q1=v1&q2=v2&q3#fragment").Dump();
new SimpleUri("p/a/t/h?q1=v1&q2=v2&q3#fragment").Dump();
new SimpleUri("p/a/t/h").Dump();
new SimpleUri("file:c:/p/a/t/h").Dump();




What do you say? Is this an optimal implementation or can it be improved?







c# parsing regex dto






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 32 mins ago

























asked 2 hours ago









t3chb0t

33.8k746111




33.8k746111












  • The EqualityComparerFactory can be found here.
    – t3chb0t
    2 hours ago


















  • The EqualityComparerFactory can be found here.
    – t3chb0t
    2 hours ago
















The EqualityComparerFactory can be found here.
– t3chb0t
2 hours ago




The EqualityComparerFactory can be found here.
– t3chb0t
2 hours ago















active

oldest

votes











Your Answer





StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");

StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f209777%2freplacing-uri-with-a-more-convenient-class%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown






























active

oldest

votes













active

oldest

votes









active

oldest

votes






active

oldest

votes
















draft saved

draft discarded




















































Thanks for contributing an answer to Code Review Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f209777%2freplacing-uri-with-a-more-convenient-class%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Quarter-circle Tiles

build a pushdown automaton that recognizes the reverse language of a given pushdown automaton?

Mont Emei